/**
  ******************************************************************************
  * @file    sym32l010_hal_gtim.c
  * @author  AE Team
  * @version 1.0.3
  * @date    2024-05-28
  * @brief   GTIM HAL module driver.
  *
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2024 SIYIMicro.
  * All rights reserved.</center></h2>
  *
  *
  ******************************************************************************
  */


/******************************************************************************/
/* Include files                                                              */
/******************************************************************************/
#include "sym32l010_hal_gtim.h"


static void GTIM_OC1_SetConfig(GTIM_TypeDef *TIMx, GTIM_OC_InitTypeDef *OC_Config);
static void GTIM_OC2_SetConfig(GTIM_TypeDef *TIMx, GTIM_OC_InitTypeDef *OC_Config);
static void GTIM_OC3_SetConfig(GTIM_TypeDef *TIMx, GTIM_OC_InitTypeDef *OC_Config);
static void GTIM_OC4_SetConfig(GTIM_TypeDef *TIMx, GTIM_OC_InitTypeDef *OC_Config);
static void GTIM_TI1_ConfigInputStage(GTIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter);
static void GTIM_TI2_ConfigInputStage(GTIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter);
static void GTIM_TI1_SetConfig(GTIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, uint32_t TIM_ICFilter);
static void GTIM_TI2_SetConfig(GTIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, uint32_t TIM_ICFilter);
static void GTIM_TI3_SetConfig(GTIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, uint32_t TIM_ICFilter);
static void GTIM_TI4_SetConfig(GTIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, uint32_t TIM_ICFilter);
static void GTIM_ITRx_SetConfig(GTIM_TypeDef *TIMx, uint32_t InputTriggerSource);
static HAL_StatusTypeDef GTIM_SlaveTimer_SetConfig(GTIM_HandleTypeDef *htim, GTIM_SlaveConfigTypeDef *sSlaveConfig);


/*******************************************************************************
  * GTIM 基础时基相关函数:
  * HAL_GTIM_Base_Init
  * HAL_GTIM_Base_DeInit
  * HAL_GTIM_Base_Start
  * HAL_GTIM_Base_Stop
  * HAL_GTIM_Base_Start_IT
  * HAL_GTIM_Base_Stop_IT
  */

/*******************************************************************************
  * @brief  GTIM 时基初始化
  * @param  htim      : GTIM句柄指针
  * @retval HAL status
  * @note   1.需通过APBENx寄存器使能GTIM的时钟后，才可调用该函数
  *         2.由于在中心对齐模式计数方向为ReadOnly属性，因此计数模式从中心对齐模式
  *           切换成边沿对齐模式（或相反操作）时需要复位GTIM，以免发生计数方向错误。
  */
HAL_StatusTypeDef HAL_GTIM_Base_Init(GTIM_HandleTypeDef *htim)
{
    if (htim == NULL)
    {
        return HAL_ERROR;
    }

    // 配置GTIM时基参数
    GTIM_Base_SetConfig(htim->Instance, &htim->Init);

    return HAL_OK;
}

/*******************************************************************************
  * @brief  GTIM 时基反初始化
  * @param  htim      : GTIM句柄指针
  * @retval HAL status
  * @note   需通过APBENx寄存器使能GTIM的时钟后，才可调用该函数
  */
HAL_StatusTypeDef HAL_GTIM_Base_DeInit(GTIM_HandleTypeDef *htim)
{
    // 关闭GTIM使能控制
    HAL_GTIM_DISABLE(htim);

    return HAL_OK;
}

/*******************************************************************************
  * @brief  启动 GTIM时基
  * @param  htim      : GTIM句柄指针
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_Base_Start(GTIM_HandleTypeDef *htim)
{
    uint32_t tmpsmcr;

    // 使能GTIM (除触发启动模式)
    tmpsmcr = htim->Instance->SMCR & GTIM_SMCR_SMS;
    if (!((tmpsmcr == GTIM_SLAVEMODE_TRIGGER) || (tmpsmcr == GTIM_SLAVEMODE_COMBINED_RESETTRIGGER)))
    {
        HAL_GTIM_ENABLE(htim);
    }

    return HAL_OK;
}

/*******************************************************************************
  * @brief  停止 GTIM 时基
  * @param  htim      : GTIM句柄指针
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_Base_Stop(GTIM_HandleTypeDef *htim)
{
    // 关闭GTIM使能控制
    HAL_GTIM_DISABLE(htim);

    return HAL_OK;
}

/*******************************************************************************
  * @brief  启动 GTIM 时基并开启更新中断
  * @param  htim      : GTIM句柄指针
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_Base_Start_IT(GTIM_HandleTypeDef *htim)
{
    uint32_t tmpsmcr;

    // 使能GTIM的UPDATE中断
    HAL_GTIM_ENABLE_IT(htim, GTIM_IT_SOURCE_UPDATE);

    // 使能GTIM (除触发启动模式)
    tmpsmcr = htim->Instance->SMCR & GTIM_SMCR_SMS;
    if (!((tmpsmcr == GTIM_SLAVEMODE_TRIGGER) || (tmpsmcr == GTIM_SLAVEMODE_COMBINED_RESETTRIGGER)))
    {
        HAL_GTIM_ENABLE(htim);
    }

    return HAL_OK;
}

/*******************************************************************************
  * @brief  停止 GTIM时基并关闭更新中断
  * @param  htim      : GTIM句柄指针
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_Base_Stop_IT(GTIM_HandleTypeDef *htim)
{
    // 关闭GTIM的UPDATE中断
    HAL_GTIM_DISABLE_IT(htim, GTIM_IT_SOURCE_UPDATE);

    // 关闭GTIM使能控制
    HAL_GTIM_DISABLE(htim);

    return HAL_OK;
}


/*******************************************************************************
  * GTIM 比较匹配相关函数:
  * HAL_GTIM_OC_Init
  * HAL_GTIM_OC_DeInit
  * HAL_GTIM_OC_Start
  * HAL_GTIM_OC_Stop
  * HAL_GTIM_OC_Start_IT
  * HAL_GTIM_OC_Stop_IT
  */

/*******************************************************************************
  * @brief  GTIM 输出比较模式初始化
  * @param  htim      : GTIM句柄指针
  * @retval HAL status
  * @note   1.需通过APBENx寄存器使能GTIM的时钟后，才可调用该函数
  *         2.由于在中心对齐模式计数方向为ReadOnly属性，因此计数模式从中心对齐模式
  *           切换成边沿对齐模式（或相反操作）时需要复位GTIM，以免发生计数方向错误。
  */
HAL_StatusTypeDef HAL_GTIM_OC_Init(GTIM_HandleTypeDef *htim)
{
    if (htim == NULL)
    {
        return HAL_ERROR;
    }

    // 配置GTIM输出比较模式的时基参数
    GTIM_Base_SetConfig(htim->Instance, &htim->Init);

    return HAL_OK;
}

/*******************************************************************************
  * @brief  GTIM 输出比较模式反初始化
  * @param  htim      : GTIM句柄指针
  * @retval HAL status
  * @note   需通过APBENx寄存器使能GTIM的时钟后，才可调用该函数
  */
HAL_StatusTypeDef HAL_GTIM_OC_DeInit(GTIM_HandleTypeDef *htim)
{
    // 关闭GTIM使能控制
    HAL_GTIM_DISABLE(htim);

    return HAL_OK;
}

/*******************************************************************************
  * @brief  启动 GTIM 生成输出比较信号
  * @param  htim      : GTIM句柄指针
  * @param  Channel   : 需要被开启的输出比较通道
  *                     @arg GTIM_CHANNEL_1: GTIM 通道1
  *                     @arg GTIM_CHANNEL_2: GTIM 通道2
  *                     @arg GTIM_CHANNEL_3: GTIM 通道3
  *                     @arg GTIM_CHANNEL_4: GTIM 通道4
  *                     @arg GTIM_CHANNEL_ALL: GTIM的所有通道
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_OC_Start(GTIM_HandleTypeDef *htim, uint32_t Channel)
{
    uint32_t tmpsmcr;

    // 开启输出比较通道
    GTIM_CCxChannelCmd(htim->Instance, Channel, GTIM_CCx_ENABLE);

    // 使能GTIM (除触发启动模式)
    tmpsmcr = htim->Instance->SMCR & GTIM_SMCR_SMS;
    if (!((tmpsmcr == GTIM_SLAVEMODE_TRIGGER) || (tmpsmcr == GTIM_SLAVEMODE_COMBINED_RESETTRIGGER)))
    {
        HAL_GTIM_ENABLE(htim);
    }

    return HAL_OK;
}

/*******************************************************************************
  * @brief  停止 GTIM 生成输出比较信号
  * @param  htim      : GTIM句柄指针
  * @param  Channel   : 需要被关闭的输出比较通道
  *                     @arg GTIM_CHANNEL_1: GTIM 通道1
  *                     @arg GTIM_CHANNEL_2: GTIM 通道2
  *                     @arg GTIM_CHANNEL_3: GTIM 通道3
  *                     @arg GTIM_CHANNEL_4: GTIM 通道4
  *                     @arg GTIM_CHANNEL_ALL: GTIM的所有通道
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_OC_Stop(GTIM_HandleTypeDef *htim, uint32_t Channel)
{
    // 关闭输出比较通道
    GTIM_CCxChannelCmd(htim->Instance, Channel, GTIM_CCx_DISABLE);

    // 关闭GTIM使能控制
    HAL_GTIM_DISABLE(htim);

    return HAL_OK;
}

/*******************************************************************************
  * @brief  启动 GTIM 生成输出比较信号并开启通道的中断
  * @param  htim      : GTIM句柄指针
  * @param  Channel   : 需要被开启的输出比较通道
  *                     @arg GTIM_CHANNEL_1: GTIM 通道1
  *                     @arg GTIM_CHANNEL_2: GTIM 通道2
  *                     @arg GTIM_CHANNEL_3: GTIM 通道3
  *                     @arg GTIM_CHANNEL_4: GTIM 通道4
  *                     @arg GTIM_CHANNEL_ALL: GTIM的所有通道
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_OC_Start_IT(GTIM_HandleTypeDef *htim, uint32_t Channel)
{
    uint32_t tmpsmcr;

    switch (Channel)
    {
        case GTIM_CHANNEL_1:
            HAL_GTIM_ENABLE_IT(htim, GTIM_IT_SOURCE_CC1);
            break;
        case GTIM_CHANNEL_2:
            HAL_GTIM_ENABLE_IT(htim, GTIM_IT_SOURCE_CC2);
            break;
        case GTIM_CHANNEL_3:
            HAL_GTIM_ENABLE_IT(htim, GTIM_IT_SOURCE_CC3);
            break;
        case GTIM_CHANNEL_4:
            HAL_GTIM_ENABLE_IT(htim, GTIM_IT_SOURCE_CC4);
            break;
        case GTIM_CHANNEL_ALL:
            HAL_GTIM_ENABLE_IT(htim, GTIM_IT_SOURCE_CC1 | GTIM_IT_SOURCE_CC2 |
                                     GTIM_IT_SOURCE_CC3 | GTIM_IT_SOURCE_CC4 );
            break;
        default:
            break;
    }

    // 开启输出比较通道
    GTIM_CCxChannelCmd(htim->Instance, Channel, GTIM_CCx_ENABLE);

    // 使能GTIM (除触发启动模式)
    tmpsmcr = htim->Instance->SMCR & GTIM_SMCR_SMS;
    if (!((tmpsmcr == GTIM_SLAVEMODE_TRIGGER) || (tmpsmcr == GTIM_SLAVEMODE_COMBINED_RESETTRIGGER)))
    {
        HAL_GTIM_ENABLE(htim);
    }

    return HAL_OK;
}

/*******************************************************************************
  * @brief  停止 GTIM 生成输出比较信号并关闭通道的中断
  * @param  htim      : GTIM句柄指针
  * @param  Channel   : 需要被关闭的输出比较通道
  *                     @arg GTIM_CHANNEL_1: GTIM 通道1
  *                     @arg GTIM_CHANNEL_2: GTIM 通道2
  *                     @arg GTIM_CHANNEL_3: GTIM 通道3
  *                     @arg GTIM_CHANNEL_4: GTIM 通道4
  *                     @arg GTIM_CHANNEL_ALL: GTIM的所有通道
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_OC_Stop_IT(GTIM_HandleTypeDef *htim, uint32_t Channel)
{
    switch (Channel)
    {
        case GTIM_CHANNEL_1:
            HAL_GTIM_DISABLE_IT(htim, GTIM_IT_SOURCE_CC1);
            break;
        case GTIM_CHANNEL_2:
            HAL_GTIM_DISABLE_IT(htim, GTIM_IT_SOURCE_CC2);
            break;
        case GTIM_CHANNEL_3:
            HAL_GTIM_DISABLE_IT(htim, GTIM_IT_SOURCE_CC3);
            break;
        case GTIM_CHANNEL_4:
            HAL_GTIM_DISABLE_IT(htim, GTIM_IT_SOURCE_CC4);
            break;
        case GTIM_CHANNEL_ALL:
            HAL_GTIM_DISABLE_IT(htim, GTIM_IT_SOURCE_CC1 | GTIM_IT_SOURCE_CC2 |
                                      GTIM_IT_SOURCE_CC3 | GTIM_IT_SOURCE_CC4);
            break;
        default:
            break;
    }

    // 关闭输出比较通道
    GTIM_CCxChannelCmd(htim->Instance, Channel, GTIM_CCx_DISABLE);

    // 关闭GTIM使能控制
    HAL_GTIM_DISABLE(htim);

    return HAL_OK;
}


/*******************************************************************************
  * GTIM PWM输出相关函数:
  * HAL_GTIM_PWM_Init
  * HAL_GTIM_PWM_DeInit
  * HAL_GTIM_PWM_Start
  * HAL_GTIM_PWM_Stop
  * HAL_GTIM_PWM_Start_IT
  * HAL_GTIM_PWM_Stop_IT
  */

/*******************************************************************************
  * @brief  GTIM PWM模式初始化
  * @param  htim      : GTIM句柄指针
  * @retval HAL status
  * @note   1.需通过APBENx寄存器使能GTIM的时钟后，才可调用该函数
  *         2.由于在中心对齐模式计数方向为ReadOnly属性，因此计数模式从中心对齐模式
  *           切换成边沿对齐模式（或相反操作）时需要复位GTIM，以免发生计数方向错误。
  */
HAL_StatusTypeDef HAL_GTIM_PWM_Init(GTIM_HandleTypeDef *htim)
{
    return HAL_GTIM_OC_Init(htim);
}

/*******************************************************************************
  * @brief  GTIM PWM模式反初始化
  * @param  htim      : GTIM句柄指针
  * @retval HAL status
  * @note   需通过APBENx寄存器使能GTIM的时钟后，才可调用该函数
  */
HAL_StatusTypeDef HAL_GTIM_PWM_DeInit(GTIM_HandleTypeDef *htim)
{
    return HAL_GTIM_OC_DeInit(htim);
}

/*******************************************************************************
  * @brief  启动 GTIM 生成PWM信号
  * @param  htim      : GTIM句柄指针
  * @param  Channel   : 需要被开启的PWM通道
  *                     @arg GTIM_CHANNEL_1: GTIM 通道1
  *                     @arg GTIM_CHANNEL_2: GTIM 通道2
  *                     @arg GTIM_CHANNEL_3: GTIM 通道3
  *                     @arg GTIM_CHANNEL_4: GTIM 通道4
  *                     @arg GTIM_CHANNEL_ALL: GTIM的所有通道
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_PWM_Start(GTIM_HandleTypeDef *htim, uint32_t Channel)
{
    return HAL_GTIM_OC_Start(htim, Channel);
}

/*******************************************************************************
  * @brief  停止 GTIM 生成PWM信号
  * @param  htim      : GTIM句柄指针
  * @param  Channel   : 需要被关闭的PWM通道
  *                     @arg GTIM_CHANNEL_1: GTIM 通道1
  *                     @arg GTIM_CHANNEL_2: GTIM 通道2
  *                     @arg GTIM_CHANNEL_3: GTIM 通道3
  *                     @arg GTIM_CHANNEL_4: GTIM 通道4
  *                     @arg GTIM_CHANNEL_ALL: GTIM的所有通道
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_PWM_Stop(GTIM_HandleTypeDef *htim, uint32_t Channel)
{
    return HAL_GTIM_OC_Stop(htim, Channel);
}

/*******************************************************************************
  * @brief  启动 GTIM 生成PWM信号并开启通道的中断
  * @param  htim      : GTIM句柄指针
  * @param  Channel   : 需要被开启的PWM通道
  *                     @arg GTIM_CHANNEL_1: GTIM 通道1
  *                     @arg GTIM_CHANNEL_2: GTIM 通道2
  *                     @arg GTIM_CHANNEL_3: GTIM 通道3
  *                     @arg GTIM_CHANNEL_4: GTIM 通道4
  *                     @arg GTIM_CHANNEL_ALL: GTIM的所有通道
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_PWM_Start_IT(GTIM_HandleTypeDef *htim, uint32_t Channel)
{
    return HAL_GTIM_OC_Start_IT(htim, Channel);
}

/*******************************************************************************
  * @brief  停止 GTIM 生成PWM信号并关闭通道的中断
  * @param  htim      : GTIM句柄指针
  * @param  Channel   : 需要被关闭的PWM通道
  *                     @arg GTIM_CHANNEL_1: GTIM 通道1
  *                     @arg GTIM_CHANNEL_2: GTIM 通道2
  *                     @arg GTIM_CHANNEL_3: GTIM 通道3
  *                     @arg GTIM_CHANNEL_4: GTIM 通道4
  *                     @arg GTIM_CHANNEL_ALL: GTIM的所有通道
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_PWM_Stop_IT(GTIM_HandleTypeDef *htim, uint32_t Channel)
{
    return HAL_GTIM_OC_Stop_IT(htim, Channel);
}


/*******************************************************************************
  * GTIM One Pulse输出相关函数:
  * HAL_GTIM_OnePulse_Init
  * HAL_GTIM_OnePulse_DeInit
  * HAL_GTIM_OnePulse_Start
  * HAL_GTIM_OnePulse_Stop
  * HAL_GTIM_OnePulse_Start_IT
  * HAL_GTIM_OnePulse_Stop_IT
  */

/*******************************************************************************
  * @brief  GTIM One Pulse模式初始化
  * @param  htim        : GTIM句柄指针
  * @param  OnePulseMode: 选择One pulse模式
  *                       @arg GTIM_OPMODE_SINGLE: 只产生一次One pulse.
  *                       @arg GTIM_OPMODE_REPETITIVE: 产生重复脉冲.
  * @retval HAL status
  * @note   1.需通过APBENx寄存器使能GTIM的时钟后，才可调用该函数
  *         2.由于在中心对齐模式计数方向为ReadOnly属性，因此计数模式从中心对齐模式
  *           切换成边沿对齐模式（或相反操作）时需要复位GTIM，以免发生计数方向错误。
  */
HAL_StatusTypeDef HAL_GTIM_OnePulse_Init(GTIM_HandleTypeDef *htim, uint32_t OnePulseMode)
{
    if (HAL_GTIM_OC_Init(htim) == HAL_ERROR)
    {
        return HAL_ERROR;
    }

    // 配置OPM模式
    REGBITS_MODIFY(htim->Instance->CR1, GTIMx_CR1_OPM_Msk, OnePulseMode);

    return HAL_OK;
}

/*******************************************************************************
  * @brief  GTIM One Pulse模式反初始化
  * @param  htim      : GTIM句柄指针
  * @retval HAL status
  * @note   需通过APBENx寄存器使能GTIM的时钟后，才可调用该函数
  */
HAL_StatusTypeDef HAL_GTIM_OnePulse_DeInit(GTIM_HandleTypeDef *htim)
{
    return HAL_GTIM_OC_DeInit(htim);
}

/*******************************************************************************
  * @brief  启动 GTIM 生成 OnePulse 信号
  * @param  htim         : GTIM句柄指针
  * @param  OutputChannel: 需要被开启的输出OnePulse的通道
  *                        @arg GTIM_CHANNEL_1: GTIM 通道1
  *                        @arg GTIM_CHANNEL_2: GTIM 通道2
  *                        @arg GTIM_CHANNEL_3: GTIM 通道3
  *                        @arg GTIM_CHANNEL_4: GTIM 通道4
  *                        @arg GTIM_CHANNEL_ALL: GTIM的所有通道
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_OnePulse_Start(GTIM_HandleTypeDef *htim, uint32_t OutputChannel)
{
    return HAL_GTIM_OC_Start(htim, OutputChannel);
}

/*******************************************************************************
  * @brief  停止 GTIM 生成  OnePulse  信号
  * @param  htim         : GTIM句柄指针
  * @param  OutputChannel: 需要被关闭的输出OnePulse的通道
  *                        @arg GTIM_CHANNEL_1: GTIM 通道1
  *                        @arg GTIM_CHANNEL_2: GTIM 通道2
  *                        @arg GTIM_CHANNEL_3: GTIM 通道3
  *                        @arg GTIM_CHANNEL_4: GTIM 通道4
  *                        @arg GTIM_CHANNEL_ALL: GTIM的所有通道
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_OnePulse_Stop(GTIM_HandleTypeDef *htim, uint32_t OutputChannel)
{
    return HAL_GTIM_OC_Stop(htim, OutputChannel);
}

/*******************************************************************************
  * @brief  启动 GTIM 生成 OnePulse 信号并开启通道的中断
  * @param  htim         : GTIM句柄指针
  * @param  OutputChannel: 需要被开启的输出OnePulse的通道
  *                        @arg GTIM_CHANNEL_1: GTIM 通道1
  *                        @arg GTIM_CHANNEL_2: GTIM 通道2
  *                        @arg GTIM_CHANNEL_3: GTIM 通道3
  *                        @arg GTIM_CHANNEL_4: GTIM 通道4
  *                        @arg GTIM_CHANNEL_ALL: GTIM的所有通道
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_OnePulse_Start_IT(GTIM_HandleTypeDef *htim, uint32_t OutputChannel)
{
    return HAL_GTIM_OC_Start_IT(htim, OutputChannel);
}

/*******************************************************************************
  * @brief  停止 GTIM 生成 OnePulse 信号并关闭通道的中断
  * @param  htim         : GTIM句柄指针
  * @param  OutputChannel: 需要被关闭的输出OnePulse的通道
  *                        @arg GTIM_CHANNEL_1: GTIM 通道1
  *                        @arg GTIM_CHANNEL_2: GTIM 通道2
  *                        @arg GTIM_CHANNEL_3: GTIM 通道3
  *                        @arg GTIM_CHANNEL_4: GTIM 通道4
  *                        @arg GTIM_CHANNEL_ALL: GTIM的所有通道
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_OnePulse_Stop_IT(GTIM_HandleTypeDef *htim, uint32_t OutputChannel)
{
    return HAL_GTIM_OC_Stop_IT(htim, OutputChannel);
}


/*******************************************************************************
  * GTIM 输入捕获相关函数:
  * HAL_GTIM_IC_Init
  * HAL_GTIM_IC_DeInit
  * HAL_GTIM_IC_Start
  * HAL_GTIM_IC_Stop
  * HAL_GTIM_IC_Start_IT
  * HAL_GTIM_IC_Stop_IT
  */

/*******************************************************************************
  * @brief  初始化 GTIM 输入捕获模式时基
  * @param  htim      : GTIM句柄指针
  * @retval HAL status
  * @note   1.需通过APBENx寄存器使能GTIM的时钟后，才可调用该函数
  *         2.由于在中心对齐模式计数方向为ReadOnly属性，因此计数模式从中心对齐模式
  *           切换成边沿对齐模式（或相反操作）时需要复位GTIM，以免发生计数方向错误。
  */
HAL_StatusTypeDef HAL_GTIM_IC_Init(GTIM_HandleTypeDef *htim)
{
    if (htim == NULL)
    {
        return HAL_ERROR;
    }

    // 配置GTIM输入捕获模式的时基参数
    GTIM_Base_SetConfig(htim->Instance, &htim->Init);

    return HAL_OK;
}

/*******************************************************************************
  * @brief  GTIM 输入捕获模式反初始化
  * @param  htim      : GTIM句柄指针
  * @retval HAL status
  * @note   需通过APBENx寄存器使能GTIM的时钟后，才可调用该函数
  */
HAL_StatusTypeDef HAL_GTIM_IC_DeInit(GTIM_HandleTypeDef *htim)
{
    // 关闭GTIM使能控制
    HAL_GTIM_DISABLE(htim);

    return HAL_OK;
}

/*******************************************************************************
  * @brief  启动 GTIM 输入捕获测量
  * @param  htim      : GTIM句柄指针
  * @param  Channel   : 需要被开启的输入捕获通道
  *                     @arg GTIM_CHANNEL_1: GTIM 通道1
  *                     @arg GTIM_CHANNEL_2: GTIM 通道2
  *                     @arg GTIM_CHANNEL_3: GTIM 通道3
  *                     @arg GTIM_CHANNEL_4: GTIM 通道4
  *                     @arg GTIM_CHANNEL_ALL: GTIM的所有通道
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_IC_Start(GTIM_HandleTypeDef *htim, uint32_t Channel)
{
    uint32_t tmpsmcr;

    // 开启输入捕获通道
    GTIM_CCxChannelCmd(htim->Instance, Channel, GTIM_CCx_ENABLE);

    // 使能GTIM (除触发启动模式)
    tmpsmcr = htim->Instance->SMCR & GTIM_SMCR_SMS;
    if (!((tmpsmcr == GTIM_SLAVEMODE_TRIGGER) || (tmpsmcr == GTIM_SLAVEMODE_COMBINED_RESETTRIGGER)))
    {
        HAL_GTIM_ENABLE(htim);
    }

    return HAL_OK;
}

/*******************************************************************************
  * @brief  停止 GTIM 输入捕获测量
  * @param  htim      : GTIM句柄指针
  * @param  Channel   : 需要被关闭的输入捕获通道
  *                     @arg GTIM_CHANNEL_1: GTIM 通道1
  *                     @arg GTIM_CHANNEL_2: GTIM 通道2
  *                     @arg GTIM_CHANNEL_3: GTIM 通道3
  *                     @arg GTIM_CHANNEL_4: GTIM 通道4
  *                     @arg GTIM_CHANNEL_ALL: GTIM的所有通道
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_IC_Stop(GTIM_HandleTypeDef *htim, uint32_t Channel)
{
    // 关闭输入捕获通道
    GTIM_CCxChannelCmd(htim->Instance, Channel, GTIM_CCx_DISABLE);

    // 关闭GTIM使能控制
    HAL_GTIM_DISABLE(htim);

    return HAL_OK;
}

/*******************************************************************************
  * @brief  启动 GTIM 输入捕获测量并开启通道的输入捕获中断
  * @param  htim      : GTIM句柄指针
  * @param  Channel   : 需要被开启的输入捕获通道
  *                     @arg GTIM_CHANNEL_1: GTIM 通道1
  *                     @arg GTIM_CHANNEL_2: GTIM 通道2
  *                     @arg GTIM_CHANNEL_3: GTIM 通道3
  *                     @arg GTIM_CHANNEL_4: GTIM 通道4
  *                     @arg GTIM_CHANNEL_ALL: GTIM的所有通道
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_IC_Start_IT(GTIM_HandleTypeDef *htim, uint32_t Channel)
{
    uint32_t tmpsmcr;

    switch (Channel)
    {
        case GTIM_CHANNEL_1:
            HAL_GTIM_ENABLE_IT(htim, GTIM_IT_SOURCE_CC1);
            break;
        case GTIM_CHANNEL_2:
            HAL_GTIM_ENABLE_IT(htim, GTIM_IT_SOURCE_CC2);
            break;
        case GTIM_CHANNEL_3:
            HAL_GTIM_ENABLE_IT(htim, GTIM_IT_SOURCE_CC3);
            break;
        case GTIM_CHANNEL_4:
            HAL_GTIM_ENABLE_IT(htim, GTIM_IT_SOURCE_CC4);
            break;
        case GTIM_CHANNEL_ALL:
            HAL_GTIM_ENABLE_IT(htim, GTIM_IT_SOURCE_CC1 | GTIM_IT_SOURCE_CC2 |
                                     GTIM_IT_SOURCE_CC3 | GTIM_IT_SOURCE_CC4);
            break;
        default:
            break;
    }

    // 开启输入捕获通道
    GTIM_CCxChannelCmd(htim->Instance, Channel, GTIM_CCx_ENABLE);

    // 使能GTIM (除触发启动模式)
    tmpsmcr = htim->Instance->SMCR & GTIM_SMCR_SMS;
    if (!((tmpsmcr == GTIM_SLAVEMODE_TRIGGER) || (tmpsmcr == GTIM_SLAVEMODE_COMBINED_RESETTRIGGER)))
    {
        HAL_GTIM_ENABLE(htim);
    }

    return HAL_OK;
}

/*******************************************************************************
  * @brief  停止 GTIM 输入捕获测量并关闭通道的输入捕获中断
  * @param  htim      : GTIM句柄指针
  * @param  Channel   : 需要被关闭的输出比较通道
  *                     @arg GTIM_CHANNEL_1: GTIM 通道1
  *                     @arg GTIM_CHANNEL_2: GTIM 通道2
  *                     @arg GTIM_CHANNEL_3: GTIM 通道3
  *                     @arg GTIM_CHANNEL_4: GTIM 通道4
  *                     @arg GTIM_CHANNEL_ALL: GTIM的所有通道
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_IC_Stop_IT(GTIM_HandleTypeDef *htim, uint32_t Channel)
{
    switch (Channel)
    {
        case GTIM_CHANNEL_1:
            HAL_GTIM_DISABLE_IT(htim, GTIM_IT_SOURCE_CC1);
            break;
        case GTIM_CHANNEL_2:
            HAL_GTIM_DISABLE_IT(htim, GTIM_IT_SOURCE_CC2);
            break;
        case GTIM_CHANNEL_3:
            HAL_GTIM_DISABLE_IT(htim, GTIM_IT_SOURCE_CC3);
            break;
        case GTIM_CHANNEL_4:
            HAL_GTIM_DISABLE_IT(htim, GTIM_IT_SOURCE_CC4);
            break;
        case GTIM_CHANNEL_ALL:
            HAL_GTIM_DISABLE_IT(htim, GTIM_IT_SOURCE_CC1 | GTIM_IT_SOURCE_CC2 |
                                      GTIM_IT_SOURCE_CC3 | GTIM_IT_SOURCE_CC4);
            break;
        default:
            break;
    }

    // 关闭输入捕获通道
    GTIM_CCxChannelCmd(htim->Instance, Channel, GTIM_CCx_DISABLE);

    // 关闭GTIM使能控制
    HAL_GTIM_DISABLE(htim);

    return HAL_OK;
}


/*******************************************************************************
  * GTIM 编码模式相关函数:
  * HAL_GTIM_Encoder_Init
  * HAL_GTIM_Encoder_DeInit
  * HAL_GTIM_Encoder_Start
  * HAL_GTIM_Encoder_Stop
  * HAL_GTIM_Encoder_Start_IT
  * HAL_GTIM_Encoder_Stop_IT
  */

/*******************************************************************************
  * @brief  初始化 GTIM 编码接口
  * @param  htim      : GTIM句柄指针
  * @param  sConfig   : GTIM编码接口配置结构体
  * @retval HAL status
  * @note   1.需通过APBENx寄存器使能GTIM的时钟后，才可调用该函数
  *         2.由于在中心对齐模式计数方向为ReadOnly属性，因此计数模式从中心对齐模式
  *           切换成边沿对齐模式（或相反操作）时需要复位GTIM，以免发生计数方向错误。
  *         3.当设置为编码模式时通道1和通道2处于保留状态，不可用于其他功能。
  *         4.编码器模式和外部时钟模式2不兼容，不能同时选择。
  */
HAL_StatusTypeDef HAL_GTIM_Encoder_Init(GTIM_HandleTypeDef *htim, GTIM_Encoder_InitTypeDef *sConfig)
{
    if (htim == NULL)
    {
        return HAL_ERROR;
    }

    REGBITS_CLR(htim->Instance->SMCR, GTIM_SMCR_SMS | GTIMx_SMCR_ECE_Msk);

    // 配置GTIM编码模式的时基参数
    GTIM_Base_SetConfig(htim->Instance, &htim->Init);

    // 设置编码模式
    REGBITS_SET(htim->Instance->SMCR, sConfig->EncoderMode);

    // 配置捕获比较通道1/2的输入映射、预分频和滤波
    REGBITS_MODIFY(htim->Instance->CCMR1CAP,
                   GTIMx_CCMR1CAP_CC1S_Msk   | GTIMx_CCMR1CAP_CC2S_Msk |
                   GTIMx_CCMR1CAP_IC1PSC_Msk | GTIMx_CCMR1CAP_IC2PSC_Msk |
                   GTIMx_CCMR1CAP_IC1F_Msk   | GTIMx_CCMR1CAP_IC2F_Msk,
                   ((sConfig->IC1Selection << 0U) | (sConfig->IC2Selection << 8U)) |
                   ((sConfig->IC1Prescaler << 0U) | (sConfig->IC2Prescaler << 8U)) |
                   ((sConfig->IC1Filter    << 4U) | (sConfig->IC2Filter    << 12U)));

    // 配置TI1和TI2的极性
    REGBITS_MODIFY(htim->Instance->CCER,
                   GTIMx_CCER_CC1P_Msk  | GTIMx_CCER_CC2P_Msk |
                   GTIMx_CCER_CC1NP_Msk | GTIMx_CCER_CC2NP_Msk,
                   (sConfig->IC1Polarity << 0U) | (sConfig->IC2Polarity << 4U));

    return HAL_OK;
}

/*******************************************************************************
  * @brief  GTIM 编码接口反初始化
  * @param  htim      : GTIM句柄指针
  * @retval HAL status
  * @note   需通过APBENx寄存器使能GTIM的时钟后，才可调用该函数
  */
HAL_StatusTypeDef HAL_GTIM_Encoder_DeInit(GTIM_HandleTypeDef *htim)
{
    // 关闭GTIM使能控制
    HAL_GTIM_DISABLE(htim);

    return HAL_OK;
}

/*******************************************************************************
  * @brief  启动 GTIM 编码接口
  * @param  htim      : GTIM句柄指针
  * @param  Channel   : 需要开启的编码输入通道
  *                     @arg GTIM_CHANNEL_1                 : GTIM通道1
  *                     @arg GTIM_CHANNEL_2                 : GTIM通道2
  *                     @arg GTIM_CHANNEL_1 | GTIM_CHANNEL_2: GTIM通道1和通道2都使用
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_Encoder_Start(GTIM_HandleTypeDef *htim, uint32_t Channel)
{
    switch (Channel)
    {
        case GTIM_CHANNEL_1:
        {
            GTIM_CCxChannelCmd(htim->Instance, GTIM_CHANNEL_1, GTIM_CCx_ENABLE);
            break;
        }
        case GTIM_CHANNEL_2:
        {
            GTIM_CCxChannelCmd(htim->Instance, GTIM_CHANNEL_2, GTIM_CCx_ENABLE);
            break;
        }
        default :
        {
            GTIM_CCxChannelCmd(htim->Instance, GTIM_CHANNEL_1, GTIM_CCx_ENABLE);
            GTIM_CCxChannelCmd(htim->Instance, GTIM_CHANNEL_2, GTIM_CCx_ENABLE);
            break;
        }
    }

    // 使能GTIM
    HAL_GTIM_ENABLE(htim);

    return HAL_OK;
}

/*******************************************************************************
  * @brief  停止 GTIM 编码接口
  * @param  htim      : GTIM句柄指针
  * @param  Channel   : 需要关闭的编码输入通道
  *                     @arg GTIM_CHANNEL_1                 : GTIM通道1
  *                     @arg GTIM_CHANNEL_2                 : GTIM通道2
  *                     @arg GTIM_CHANNEL_1 | GTIM_CHANNEL_2: GTIM通道1和通道2都关闭
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_Encoder_Stop(GTIM_HandleTypeDef *htim, uint32_t Channel)
{
    switch (Channel)
    {
        case GTIM_CHANNEL_1:
        {
            GTIM_CCxChannelCmd(htim->Instance, GTIM_CHANNEL_1, GTIM_CCx_DISABLE);
            break;
        }
        case GTIM_CHANNEL_2:
        {
            GTIM_CCxChannelCmd(htim->Instance, GTIM_CHANNEL_2, GTIM_CCx_DISABLE);
            break;
        }
        default :
        {
            GTIM_CCxChannelCmd(htim->Instance, GTIM_CHANNEL_1, GTIM_CCx_DISABLE);
            GTIM_CCxChannelCmd(htim->Instance, GTIM_CHANNEL_2, GTIM_CCx_DISABLE);
            break;
        }
    }

    // 关闭GTIM使能控制
    HAL_GTIM_DISABLE(htim);

    return HAL_OK;
}

/*******************************************************************************
  * @brief  启动 GTIM 编码接口并使能编码输入通道的捕获比较中断
  * @param  htim      : GTIM句柄指针
  * @param  Channel   : 需要开启的编码输入通道
  *                     @arg GTIM_CHANNEL_1                 : GTIM通道1
  *                     @arg GTIM_CHANNEL_2                 : GTIM通道2
  *                     @arg GTIM_CHANNEL_1 | GTIM_CHANNEL_2: GTIM通道1和通道2都使用
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_Encoder_Start_IT(GTIM_HandleTypeDef *htim, uint32_t Channel)
{
    switch (Channel)
    {
        case GTIM_CHANNEL_1:
        {
            GTIM_CCxChannelCmd(htim->Instance, GTIM_CHANNEL_1, GTIM_CCx_ENABLE);
            HAL_GTIM_ENABLE_IT(htim, GTIM_IT_SOURCE_CC1);
            break;
        }
        case GTIM_CHANNEL_2:
        {
            GTIM_CCxChannelCmd(htim->Instance, GTIM_CHANNEL_2, GTIM_CCx_ENABLE);
            HAL_GTIM_ENABLE_IT(htim, GTIM_IT_SOURCE_CC2);
            break;
        }
        default:
        {
            GTIM_CCxChannelCmd(htim->Instance, GTIM_CHANNEL_1, GTIM_CCx_ENABLE);
            GTIM_CCxChannelCmd(htim->Instance, GTIM_CHANNEL_2, GTIM_CCx_ENABLE);
            HAL_GTIM_ENABLE_IT(htim, GTIM_IT_SOURCE_CC1);
            HAL_GTIM_ENABLE_IT(htim, GTIM_IT_SOURCE_CC2);
            break;
        }
    }

    // 使能GTIM
    HAL_GTIM_ENABLE(htim);

    return HAL_OK;
}

/*******************************************************************************
  * @brief  停止 GTIM 编码接口并关闭编码输入通道的捕获比较中断
  * @param  htim      : GTIM句柄指针
  * @param  Channel   : 需要关闭的编码输入通道
  *                     @arg GTIM_CHANNEL_1                 : GTIM通道1
  *                     @arg GTIM_CHANNEL_2                 : GTIM通道2
  *                     @arg GTIM_CHANNEL_1 | GTIM_CHANNEL_2: GTIM通道1和通道2关闭
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_Encoder_Stop_IT(GTIM_HandleTypeDef *htim, uint32_t Channel)
{
    switch (Channel)
    {
        case GTIM_CHANNEL_1:
        {
            GTIM_CCxChannelCmd(htim->Instance, GTIM_CHANNEL_1, GTIM_CCx_DISABLE);
            HAL_GTIM_DISABLE_IT(htim, GTIM_IT_SOURCE_CC1);
            break;
        }
        case GTIM_CHANNEL_2:
        {
            GTIM_CCxChannelCmd(htim->Instance, GTIM_CHANNEL_2, GTIM_CCx_DISABLE);
            HAL_GTIM_DISABLE_IT(htim, GTIM_IT_SOURCE_CC2);
            break;
        }
        default:
        {
            GTIM_CCxChannelCmd(htim->Instance, GTIM_CHANNEL_1, GTIM_CCx_DISABLE);
            GTIM_CCxChannelCmd(htim->Instance, GTIM_CHANNEL_2, GTIM_CCx_DISABLE);
            HAL_GTIM_DISABLE_IT(htim, GTIM_IT_SOURCE_CC1);
            HAL_GTIM_DISABLE_IT(htim, GTIM_IT_SOURCE_CC2);
            break;
        }
    }

    // 关闭GTIM使能控制
    HAL_GTIM_DISABLE(htim);

    return HAL_OK;
}


/*******************************************************************************
  * GTIM Hall Sensor相关函数:
  * HAL_GTIM_HallSensor_Init
  * HAL_GTIM_HallSensor_DeInit
  * HAL_GTIM_HallSensor_Start
  * HAL_GTIM_HallSensor_Stop
  * HAL_GTIM_HallSensor_Start_IT
  * HAL_GTIM_HallSensor_Stop_IT
  */

/*******************************************************************************
  * @brief  初始化 GTIM 霍尔传感器接口
  * @param  htim      : GTIM句柄指针
  * @param  sConfig   : GTIM霍尔传感器接口配置结构体
  * @retval HAL status
  * @note   1.需通过APBENx寄存器使能GTIM的时钟后，才可调用该函数
  *         2.当设置为霍尔传感器接口模式时通道1和通道2处于保留状态，不可用于其他功能。
  */
HAL_StatusTypeDef HAL_GTIM_HallSensor_Init(GTIM_HandleTypeDef *htim, GTIM_HallSensor_InitTypeDef *sConfig)
{
    GTIM_OC_InitTypeDef OC_Config;

    if (htim == NULL)
    {
        return HAL_ERROR;
    }

    // 配置GTIM的时基参数
    GTIM_Base_SetConfig(htim->Instance, &htim->Init);

    // 配置通道1为输入状态，用于连接霍尔传感器的连接3通道输出
    GTIM_TI1_SetConfig(htim->Instance, sConfig->IC1Polarity, GTIM_ICSELECTION_TRGI, sConfig->IC1Filter);

    // 配置输入捕获1预分频值
    REGBITS_MODIFY(htim->Instance->CCMR1CAP, GTIMx_CCMR1CAP_IC1PSC_Msk, sConfig->IC1Prescaler);

    // 使能霍尔传感器接口（CH1、CH2、CH3管脚信号三通道异或后输入）
    REGBITS_SET(htim->Instance->CR2, GTIMx_CR2_TI1S_Msk);

    // 设置GTIM为从模式的触发复位模式，触发源来自GTIM_TS_TI1F_ED信号。
    REGBITS_MODIFY(htim->Instance->SMCR,
                   GTIM_SMCR_TS | GTIM_SMCR_SMS,
                   (uint32_t)GTIM_TS_TI1F_ED | (uint32_t)GTIM_SLAVEMODE_RESET);

    // 配置通道2为PWM2模式，并设置期望的换算延时时间
    OC_Config.OCFastMode = GTIM_OCFAST_DISABLE;
    OC_Config.OCMode = GTIM_OCMODE_PWM2;
    OC_Config.OCPolarity = GTIM_OCPOLARITY_HIGH;
    OC_Config.Pulse = sConfig->Commutation_Delay;

    GTIM_OC2_SetConfig(htim->Instance, &OC_Config);

    // 通过TRGO输出OC2REF信号
    REGBITS_MODIFY(htim->Instance->CR2, GTIM_CR2_MMS, GTIM_TRGO_OC2REF);

    return HAL_OK;
}

/*******************************************************************************
  * @brief  GTIM 霍尔传感器接口反初始化
  * @param  htim      : GTIM句柄指针
  * @retval HAL status
  * @note   需通过APBENx寄存器使能GTIM的时钟后，才可调用该函数
  */
HAL_StatusTypeDef HAL_GTIM_HallSensor_DeInit(GTIM_HandleTypeDef *htim)
{
    // 关闭GTIM使能控制
    HAL_GTIM_DISABLE(htim);

    return HAL_OK;
}

/*******************************************************************************
  * @brief  启动 GTIM 霍尔传感器接口
  * @param  htim      : GTIM句柄指针
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_HallSensor_Start(GTIM_HandleTypeDef *htim)
{
    uint32_t tmpsmcr;

    // 使能输入捕获通道1(在霍尔传感器接口中，可以使用的通道是GTIM_CHANNEL_1、GTIM_CHANNEL_2和GTIM_CHANNEL_3)
    GTIM_CCxChannelCmd(htim->Instance, GTIM_CHANNEL_1, GTIM_CCx_ENABLE);

    // 使能GTIM (除触发启动模式)
    tmpsmcr = htim->Instance->SMCR & GTIM_SMCR_SMS;
    if (!((tmpsmcr == GTIM_SLAVEMODE_TRIGGER) || (tmpsmcr == GTIM_SLAVEMODE_COMBINED_RESETTRIGGER)))
    {
        HAL_GTIM_ENABLE(htim);
    }

    return HAL_OK;
}

/*******************************************************************************
  * @brief  停止 GTIM 霍尔传感器接口
  * @param  htim      : GTIM句柄指针
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_HallSensor_Stop(GTIM_HandleTypeDef *htim)
{
    // 关闭输入捕获通道1(在霍尔传感器接口中，可以使用的通道是GTIM_CHANNEL_1、GTIM_CHANNEL_2和GTIM_CHANNEL_3)
    GTIM_CCxChannelCmd(htim->Instance, GTIM_CHANNEL_1, GTIM_CCx_DISABLE);

    // 关闭GTIM使能控制
    HAL_GTIM_DISABLE(htim);

    return HAL_OK;
}

/*******************************************************************************
  * @brief  启动 GTIM 霍尔传感器接口并使能捕获比较通道1中断
  * @param  htim      : GTIM句柄指针
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_HallSensor_Start_IT(GTIM_HandleTypeDef *htim)
{
    // 使能比较匹配通道1中断
    HAL_GTIM_ENABLE_IT(htim, GTIM_IT_SOURCE_CC1);

    return HAL_GTIM_HallSensor_Start(htim);
}

/*******************************************************************************
  * @brief  停止 GTIM 霍尔传感器接口并关闭捕获比较通道1中断
  * @param  htim      : GTIM句柄指针
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_HallSensor_Stop_IT(GTIM_HandleTypeDef *htim)
{
    // 关闭输入捕获通道1(在霍尔传感器接口中，可以使用的通道是GTIM_CHANNEL_1、GTIM_CHANNEL_2和GTIM_CHANNEL_3)
    GTIM_CCxChannelCmd(htim->Instance, GTIM_CHANNEL_1, GTIM_CCx_DISABLE);

    // 关闭比较匹配通道1只能中断
    HAL_GTIM_DISABLE_IT(htim, GTIM_IT_SOURCE_CC1);

    // 关闭GTIM使能控制
    HAL_GTIM_DISABLE(htim);

    return HAL_OK;
}


/*******************************************************************************
  * GTIM 控制/配置相关函数:
  * HAL_GTIM_OC_ConfigChannel
  * HAL_GTIM_PWM_ConfigChannel
  * HAL_GTIM_OnePulse_ConfigOutChannel
  * HAL_GTIM_ConfigOCrefClear
  * HAL_GTIM_ConfigClockSource
  * HAL_GTIM_ConfigTI1Input
  * HAL_GTIM_SlaveConfigSynchro
  * HAL_GTIM_SlaveConfigSynchro_IT
  * HAL_GTIM_GenerateEvent
  */

/*******************************************************************************
  * @brief  GTIM 输出比较通道配置
  * @param  htim      : GTIM句柄指针
  * @param  sConfig   : GTIM输出比较初始化结构体指针
  * @param  Channel   : 需要被配置的通道
  *                     @arg GTIM_CHANNEL_1: GTIM 通道1
  *                     @arg GTIM_CHANNEL_2: GTIM 通道2
  *                     @arg GTIM_CHANNEL_3: GTIM 通道3
  *                     @arg GTIM_CHANNEL_4: GTIM 通道4
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_OC_ConfigChannel(GTIM_HandleTypeDef *htim,
                                            GTIM_OC_InitTypeDef *sConfig,
                                            uint32_t Channel)
{
    switch (Channel)
    {
        case GTIM_CHANNEL_1:
            GTIM_OC1_SetConfig(htim->Instance, sConfig);
            break;
        case GTIM_CHANNEL_2:
            GTIM_OC2_SetConfig(htim->Instance, sConfig);
            break;
        case GTIM_CHANNEL_3:
            GTIM_OC3_SetConfig(htim->Instance, sConfig);
            break;
        case GTIM_CHANNEL_4:
            GTIM_OC4_SetConfig(htim->Instance, sConfig);
            break;
        default:
            break;
    }

    return HAL_OK;
}

/*******************************************************************************
  * @brief  GTIM 输入捕获通道配置
  * @param  htim      : GTIM句柄指针
  * @param  sConfig   : GTIM输入捕获初始化结构体指针
  * @param  Channel   : 需要被配置的通道
  *                     @arg GTIM_CHANNEL_1: GTIM 通道1
  *                     @arg GTIM_CHANNEL_2: GTIM 通道2
  *                     @arg GTIM_CHANNEL_3: GTIM 通道3
  *                     @arg GTIM_CHANNEL_4: GTIM 通道4
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_IC_ConfigChannel(GTIM_HandleTypeDef *htim, GTIM_IC_InitTypeDef *sConfig,
                                                                      uint32_t Channel)
{
    switch (Channel)
    {
        case GTIM_CHANNEL_1:
        {
            GTIM_TI1_SetConfig(htim->Instance, sConfig->ICPolarity,
                               sConfig->ICSelection, sConfig->ICFilter);
            REGBITS_MODIFY(htim->Instance->CCMR1CAP, GTIMx_CCMR1CAP_IC1PSC_Msk,
                               (sConfig->ICPrescaler << 0U));
            break;
        }
        case GTIM_CHANNEL_2:
        {
            GTIM_TI2_SetConfig(htim->Instance, sConfig->ICPolarity,
                               sConfig->ICSelection, sConfig->ICFilter);
            REGBITS_MODIFY(htim->Instance->CCMR1CAP, GTIMx_CCMR1CAP_IC2PSC_Msk,
                               (sConfig->ICPrescaler << 8U));
            break;
        }
        case GTIM_CHANNEL_3:
        {
            GTIM_TI3_SetConfig(htim->Instance, sConfig->ICPolarity,
                               sConfig->ICSelection, sConfig->ICFilter);
            REGBITS_MODIFY(htim->Instance->CCMR2CAP, GTIMx_CCMR2CAP_IC3PSC_Msk,
                               (sConfig->ICPrescaler << 0U));
            break;
        }
        case GTIM_CHANNEL_4:
        {
            GTIM_TI4_SetConfig(htim->Instance, sConfig->ICPolarity,
                               sConfig->ICSelection, sConfig->ICFilter);
            REGBITS_MODIFY(htim->Instance->CCMR2CAP, GTIMx_CCMR2CAP_IC4PSC_Msk,
                               (sConfig->ICPrescaler << 8U));
            break;
        }
        default:
            break;
    }

    return HAL_OK;
}

/*******************************************************************************
  * @brief  GTIM PWM输出通道配置
  * @param  htim      : GTIM句柄指针
  * @param  sConfig   : GTIM PWM输出初始化结构体指针
  * @param  Channel   : 需要被配置的通道
  *                     @arg GTIM_CHANNEL_1: GTIM 通道1
  *                     @arg GTIM_CHANNEL_2: GTIM 通道2
  *                     @arg GTIM_CHANNEL_3: GTIM 通道3
  *                     @arg GTIM_CHANNEL_4: GTIM 通道4
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_PWM_ConfigChannel(GTIM_HandleTypeDef *htim,
                                            GTIM_OC_InitTypeDef *sConfig,
                                            uint32_t Channel)
{
    switch (Channel)
    {
        case GTIM_CHANNEL_1:
        {
            GTIM_OC1_SetConfig(htim->Instance, sConfig);
            REGBITS_MODIFY(htim->Instance->CCMR1CMP, GTIMx_CCMR1CMP_OC1FE_Msk,
                           GTIMx_CCMR1CMP_OC1PE_Msk | (sConfig->OCFastMode << 0U));
            break;
        }
        case GTIM_CHANNEL_2:
        {
            GTIM_OC2_SetConfig(htim->Instance, sConfig);
            REGBITS_MODIFY(htim->Instance->CCMR1CMP, GTIMx_CCMR1CMP_OC2FE_Msk,
                           GTIMx_CCMR1CMP_OC2PE_Msk | (sConfig->OCFastMode << 8U));
            break;
        }
        case GTIM_CHANNEL_3:
        {
            GTIM_OC3_SetConfig(htim->Instance, sConfig);
            REGBITS_MODIFY(htim->Instance->CCMR2CMP, GTIMx_CCMR2CMP_OC3FE_Msk,
                           GTIMx_CCMR2CMP_OC3PE_Msk | (sConfig->OCFastMode << 0U));
            break;
        }
        case GTIM_CHANNEL_4:
        {
            GTIM_OC4_SetConfig(htim->Instance, sConfig);
            REGBITS_MODIFY(htim->Instance->CCMR2CMP, GTIMx_CCMR2CMP_OC4FE_Msk,
                           GTIMx_CCMR2CMP_OC4PE_Msk | (sConfig->OCFastMode << 8U));
            break;
        }
        default:
            break;
    }

    return HAL_OK;
}

/*******************************************************************************
  * @brief  GTIM OnePulse 模式通道配置
  * @param  htim         : GTIM句柄指针
  * @param  sConfig      : GTIM OnePulse初始化结构体指针
  * @param  OutputChannel: 需要被配置的用于输出OnePulse的通道
  *                        @arg GTIM_CHANNEL_1: GTIM 通道1
  *                        @arg GTIM_CHANNEL_2: GTIM 通道2
  *                        @arg GTIM_CHANNEL_3: GTIM 通道3
  *                        @arg GTIM_CHANNEL_4: GTIM 通道4
  * @param  InputChannel : 需要被配置的用于触发启动OnePulse的通道
  *                        @arg GTIM_CHANNEL_1: GTIM 通道1
  *                        @arg GTIM_CHANNEL_2: GTIM 通道2
  * @retval HAL status
  * @note   1. OutputChannel和InputChannel不可以选择同一物理通道。
  *         2. 如果不需要使用CH1/CH2进行触发启动，请将参数InputChannel传入0。
  *         3. 如果要以最小的延时输出波形，用户可以通过调用宏 @ref HAL_GTIM_ENABLE_OCxFAST
  *            来启动快速模式。此时TIx输入信号检测到目标边沿时会强制 OCxREF 立即输出发生
  *            比较匹配时的电平，而不再等待比较匹配时刻点。
  */
HAL_StatusTypeDef HAL_GTIM_OnePulse_ConfigChannel(GTIM_HandleTypeDef *htim,
                                                  GTIM_OnePulse_InitTypeDef *sConfig,
                                                  uint32_t OutputChannel,
                                                  uint32_t InputChannel)
{
    GTIM_OC_InitTypeDef temp1;

    // 从sConfig结构体中提取输出比较的配置信息
    temp1.OCMode       = sConfig->OCMode;
    temp1.Pulse        = sConfig->Pulse;
    temp1.OCPolarity   = sConfig->OCPolarity;
    HAL_GTIM_OC_ConfigChannel(htim, &temp1, OutputChannel);

    if (OutputChannel != InputChannel)
    {
        switch (InputChannel)
        {
            case GTIM_CHANNEL_1:
            {
                GTIM_TI1_SetConfig(htim->Instance, sConfig->ICPolarity,
                                   sConfig->ICSelection, sConfig->ICFilter);

                // 清零IC1输入捕获预分频
                REGBITS_CLR(htim->Instance->CCMR1CAP, GTIMx_CCMR1CAP_IC1PSC_Msk);

                // 选择触发输入源为TI1PF1并设置为触发模式
                REGBITS_MODIFY(htim->Instance->SMCR,
                               GTIM_SMCR_TS | GTIM_SMCR_SMS,
                               (uint32_t)GTIM_TS_TI1FP1 | (uint32_t)GTIM_SLAVEMODE_TRIGGER);
                break;
            }
            case GTIM_CHANNEL_2:
            {
                GTIM_TI2_SetConfig(htim->Instance, sConfig->ICPolarity,
                                   sConfig->ICSelection, sConfig->ICFilter);

                // 清零IC2输入捕获预分频
                REGBITS_CLR(htim->Instance->CCMR1CAP, GTIMx_CCMR1CAP_IC2PSC_Msk);

                // 选择触发输入源为TI2PF2并设置为触发模式
                REGBITS_MODIFY(htim->Instance->SMCR,
                               GTIM_SMCR_TS | GTIM_SMCR_SMS,
                               (uint32_t)GTIM_TS_TI2FP2 | (uint32_t)GTIM_SLAVEMODE_TRIGGER);
                break;
            }
            default:
                break;
        }

        return HAL_OK;
    }
    else
    {
        return HAL_ERROR;
    }
}

/*******************************************************************************
  * @brief  GTIM 软件生成事件源
  * @param  htim         : GTIM句柄指针
  * @param  EventSource  : 需要生成的事件源
  *                        @arg GTIM_EVENTSOURCE_UPDATE:  更新事件源
  *                        @arg GTIM_EVENTSOURCE_CC1:     捕获比较通道1事件源
  *                        @arg GTIM_EVENTSOURCE_CC2:     捕获比较通道2事件源
  *                        @arg GTIM_EVENTSOURCE_CC3:     捕获比较通道3事件源
  *                        @arg GTIM_EVENTSOURCE_CC4:     捕获比较通道4事件源
  *                        @arg GTIM_EVENTSOURCE_CC5:     捕获比较通道5事件源
  *                        @arg GTIM_EVENTSOURCE_CC6:     捕获比较通道6事件源
  *                        @arg GTIM_EVENTSOURCE_COM:     COM事件源
  *                        @arg GTIM_EVENTSOURCE_TRIGGER: 触发事件源
  *                        @arg GTIM_EVENTSOURCE_BREAK:   刹车事件源
  *                        @arg GTIM_EVENTSOURCE_BREAK2:  刹车2事件源
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_GenerateEvent(GTIM_HandleTypeDef *htim, uint32_t EventSource)
{
    htim->Instance->EGR = EventSource;
    return HAL_OK;
}

/*******************************************************************************
  * @brief  GTIM OCRef 清零配置
  * @param  htim      : GTIM句柄指针
  * @param  sClearInputConfig: OCref清零配置结构体指针
  * @param  Channel   : 需要被配置的通道
  *                     @arg GTIM_CHANNEL_1: GTIM 通道1
  *                     @arg GTIM_CHANNEL_2: GTIM 通道2
  *                     @arg GTIM_CHANNEL_3: GTIM 通道3
  *                     @arg GTIM_CHANNEL_4: GTIM 通道4
  *                     @arg GTIM_CHANNEL_ALL: GTIM 所有通道
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_ConfigOCrefClear(GTIM_HandleTypeDef *htim,
                                            GTIM_ClearInputConfigTypeDef *sClearInputConfig,
                                            uint32_t Channel)
{
    switch (sClearInputConfig->ClearInputSource)
    {
        case GTIM_CLEARINPUTSOURCE_NONE:
        {
            REGBITS_CLR(htim->Instance->SMCR, (GTIMx_SMCR_OCCS_Msk | GTIMx_SMCR_ETF_Msk | GTIMx_SMCR_ETPS_Msk |
                                               GTIMx_SMCR_ECE_Msk | GTIMx_SMCR_ETP_Msk));
            REGBITS_CLR(htim->Instance->AF2, GTIMx_AF2_OCRSEL_Msk);
            break;
        }
        case GTIM_CLEARINPUTSOURCE_VC1_OUT:
        case GTIM_CLEARINPUTSOURCE_VC2_OUT:
        case GTIM_CLEARINPUTSOURCE_ADC_AWD:
        {
            REGBITS_CLR(htim->Instance->SMCR, GTIMx_SMCR_OCCS_Msk);
            REGBITS_MODIFY(htim->Instance->AF2, GTIMx_AF2_OCRSEL_Msk, sClearInputConfig->ClearInputSource);
            break;
        }
        case GTIM_CLEARINPUTSOURCE_ETR:
        {
            if (sClearInputConfig->ClearInputPrescaler != GTIM_CLEARINPUTPRESCALER_DIV1)
            {
                return HAL_ERROR;
            }

            GTIM_ETR_SetConfig(htim->Instance,
                               sClearInputConfig->ClearInputPrescaler,
                               sClearInputConfig->ClearInputPolarity,
                               sClearInputConfig->ClearInputFilter);
            REGBITS_SET(htim->Instance->SMCR, GTIMx_SMCR_OCCS_Msk);
            REGBITS_CLR(htim->Instance->AF2, GTIMx_AF2_OCRSEL_Msk);
            break;
        }
        default:
            break;
    }

    switch (Channel)
    {
        case GTIM_CHANNEL_1:
        {
            REGBITS_MODIFY(htim->Instance->CCMR1CMP, GTIMx_CCMR1CMP_OC1CE_Msk,
                         ((sClearInputConfig->ClearInputState == (uint32_t)DISABLE) ? 0U : GTIMx_CCMR1CMP_OC1CE_Msk));
            break;
        }
        case GTIM_CHANNEL_2:
        {
            REGBITS_MODIFY(htim->Instance->CCMR1CMP, GTIMx_CCMR1CMP_OC2CE_Msk,
                         ((sClearInputConfig->ClearInputState == (uint32_t)DISABLE) ? 0U : GTIMx_CCMR1CMP_OC2CE_Msk));
            break;
        }
        case GTIM_CHANNEL_3:
        {
            REGBITS_MODIFY(htim->Instance->CCMR2CMP, GTIMx_CCMR2CMP_OC3CE_Msk,
                         ((sClearInputConfig->ClearInputState == (uint32_t)DISABLE) ? 0U : GTIMx_CCMR2CMP_OC3CE_Msk));
            break;
        }
        case GTIM_CHANNEL_4:
        {
            REGBITS_MODIFY(htim->Instance->CCMR2CMP, GTIMx_CCMR2CMP_OC4CE_Msk,
                         ((sClearInputConfig->ClearInputState == (uint32_t)DISABLE) ? 0U : GTIMx_CCMR2CMP_OC4CE_Msk));
            break;
        }
        case GTIM_CHANNEL_ALL:
        {
            if (sClearInputConfig->ClearInputState == (uint32_t)DISABLE)
            {
                REGBITS_CLR(htim->Instance->CCMR1CMP, GTIMx_CCMR1CMP_OC1CE_Msk | GTIMx_CCMR1CMP_OC2CE_Msk);
                REGBITS_CLR(htim->Instance->CCMR2CMP, GTIMx_CCMR2CMP_OC3CE_Msk | GTIMx_CCMR2CMP_OC4CE_Msk);
            }
            else
            {
                REGBITS_SET(htim->Instance->CCMR1CMP, GTIMx_CCMR1CMP_OC1CE_Msk | GTIMx_CCMR1CMP_OC2CE_Msk);
                REGBITS_SET(htim->Instance->CCMR2CMP, GTIMx_CCMR2CMP_OC3CE_Msk | GTIMx_CCMR2CMP_OC4CE_Msk);
            }
            break;
        }
        default:
          break;
    }

    return HAL_OK;
}

/*******************************************************************************
  * @brief  GTIM 时钟源配置
  * @param  htim              : GTIM句柄指针
  * @param  sClockSourceConfig: GTIM时钟源配置结构体指针
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_ConfigClockSource(GTIM_HandleTypeDef *htim, GTIM_ClockConfigTypeDef *sClockSourceConfig)
{
    // 复位 SMS, TS, ECE, ETPS 和 ETRF 位域
    REGBITS_CLR(htim->Instance->SMCR, GTIM_SMCR_SMS | GTIM_SMCR_TS |
                                GTIMx_SMCR_ETF_Msk | GTIMx_SMCR_ETPS_Msk |
                                GTIMx_SMCR_ECE_Msk | GTIMx_SMCR_ETP_Msk);

    switch (sClockSourceConfig->ClockSource)
    {
        case GTIM_CLOCKSOURCE_INTERNAL:
        {
            break;
        }
        case GTIM_CLOCKSOURCE_ETRMODE1:
        {
            // ETR时钟源配置
            GTIM_ETR_SetConfig(htim->Instance,
                               sClockSourceConfig->ClockPrescaler,
                               sClockSourceConfig->ClockPolarity,
                               sClockSourceConfig->ClockFilter);
            // 配置外部时钟模式1和ETRF触发
            REGBITS_SET(htim->Instance->SMCR, (uint32_t)GTIM_SLAVEMODE_EXTERNAL1 |
                                              (uint32_t)GTIM_CLOCKSOURCE_ETRMODE1);
            break;
        }
        case GTIM_CLOCKSOURCE_ETRMODE2:
        {
            // ETR时钟源配置
            GTIM_ETR_SetConfig(htim->Instance,
                               sClockSourceConfig->ClockPrescaler,
                               sClockSourceConfig->ClockPolarity,
                               sClockSourceConfig->ClockFilter);
            // 配置外部时钟模式2
            REGBITS_SET(htim->Instance->SMCR, GTIMx_SMCR_ECE_Msk);
            break;
        }
        case GTIM_CLOCKSOURCE_TI1:
        {
            GTIM_TI1_ConfigInputStage(htim->Instance,
                                      sClockSourceConfig->ClockPolarity,
                                      sClockSourceConfig->ClockFilter);
            GTIM_ITRx_SetConfig(htim->Instance, (uint32_t)GTIM_CLOCKSOURCE_TI1);
            break;
        }
        case GTIM_CLOCKSOURCE_TI2:
        {
            GTIM_TI2_ConfigInputStage(htim->Instance,
                                      sClockSourceConfig->ClockPolarity,
                                      sClockSourceConfig->ClockFilter);
            GTIM_ITRx_SetConfig(htim->Instance, (uint32_t)GTIM_CLOCKSOURCE_TI2);
            break;
        }
        case GTIM_CLOCKSOURCE_TI1ED:
        {
            GTIM_TI1_ConfigInputStage(htim->Instance,
                                      sClockSourceConfig->ClockPolarity,
                                      sClockSourceConfig->ClockFilter);
            GTIM_ITRx_SetConfig(htim->Instance, (uint32_t)GTIM_CLOCKSOURCE_TI1ED);
            break;
        }
        case GTIM_CLOCKSOURCE_ITR0:
        case GTIM_CLOCKSOURCE_ITR1:
        case GTIM_CLOCKSOURCE_ITR2:
        case GTIM_CLOCKSOURCE_ITR3:
        case GTIM_CLOCKSOURCE_ITR4:
        case GTIM_CLOCKSOURCE_ITR5:
        case GTIM_CLOCKSOURCE_ITR6:
        case GTIM_CLOCKSOURCE_ITR7:
        case GTIM_CLOCKSOURCE_ITR8:
        case GTIM_CLOCKSOURCE_ITR9:
        case GTIM_CLOCKSOURCE_ITR10:
        case GTIM_CLOCKSOURCE_ITR11:
        case GTIM_CLOCKSOURCE_ITR12:
        {
            GTIM_ITRx_SetConfig(htim->Instance, (uint32_t)sClockSourceConfig->ClockSource);
            break;
        }

        default:
            break;
    }

    return HAL_OK;
}

/*******************************************************************************
  * @brief  GTIM TI1输入信号选择
  * @param  htim         : GTIM句柄指针
  * @param  TI1_Selection: TI1输入信号来源选择
  *                        @arg GTIM_TI1SELECTION_CH1:            CH1管脚信号连接到TI1输入
  *                        @arg GTIM_TI1SELECTION_XORCOMBINATION: CH1、CH2、CH3管脚信号异或后连接到TI1输入
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_ConfigTI1Input(GTIM_HandleTypeDef *htim, uint32_t TI1_Selection)
{
    REGBITS_MODIFY(htim->Instance->CR2, GTIMx_CR2_TI1S_Msk, TI1_Selection);
    return HAL_OK;
}

/*******************************************************************************
  * @brief  配置GTIM工作于从模式
  * @param  htim         : GTIM句柄指针
  * @param  sSlaveConfig : 从模式配置结构体指针
  *                        从模式可选择禁止从模式、复位模式、门控模式、触发模式、
  *                        外部时钟模式1、组合复位+触发模式、组合门控+复位模式
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_SlaveConfigSynchro(GTIM_HandleTypeDef *htim, GTIM_SlaveConfigTypeDef *sSlaveConfig)
{
    if (GTIM_SlaveTimer_SetConfig(htim, sSlaveConfig) != HAL_OK)
    {
        return HAL_ERROR;
    }

    // 关闭触发中断
    HAL_GTIM_DISABLE_IT(htim, GTIM_IT_SOURCE_TRIGGER);

    // 关闭触发请求DMA
    //HAL_GTIM_DISABLE_DMA(htim, GTIMx_DMA_TRIGGER_Msk);

    return HAL_OK;
}

/*******************************************************************************
  * @brief  配置GTIM工作于从模式并开启触发中断
  * @param  htim         : GTIM句柄指针
  * @param  sSlaveConfig : 从模式配置结构体指针
  *                        从模式可选择禁止从模式、复位模式、门控模式、触发模式、
  *                        外部时钟模式1、组合复位+触发模式、组合门控+复位模式
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_SlaveConfigSynchro_IT(GTIM_HandleTypeDef *htim,
                                                GTIM_SlaveConfigTypeDef *sSlaveConfig)
{
    if (GTIM_SlaveTimer_SetConfig(htim, sSlaveConfig) != HAL_OK)
    {
        return HAL_ERROR;
    }

    // 使能触发中断
    HAL_GTIM_ENABLE_IT(htim, GTIM_IT_SOURCE_TRIGGER);

    // 关闭触发请求DMA
    //HAL_GTIM_DISABLE_DMA(htim, GTIM_DMA_TRIGGER);

    return HAL_OK;
}


/*******************************************************************************
  * 获取 GTIM 捕获值/通道状态相关函数:
  * HAL_GTIM_ReadCapturedValue
  * HAL_GTIM_GetActiveChannel
  */

/*******************************************************************************
  * @brief  获取GTIM输入捕获值
  * @param  htim    : GTIM句柄指针
  * @param  Channel : 待获取捕获值的通道
  *                     @arg GTIM_CHANNEL_1: GTIM 通道1
  *                     @arg GTIM_CHANNEL_2: GTIM 通道2
  *                     @arg GTIM_CHANNEL_3: GTIM 通道3
  *                     @arg GTIM_CHANNEL_4: GTIM 通道4
  * @retval 输入捕获值
  */
uint32_t HAL_GTIM_ReadCapturedValue(GTIM_HandleTypeDef *htim, uint32_t Channel)
{
    uint32_t tmpreg = 0U;

    switch (Channel)
    {
        case GTIM_CHANNEL_1:
            tmpreg = htim->Instance->CCR1;
            break;
        case GTIM_CHANNEL_2:
            tmpreg = htim->Instance->CCR2;
            break;
        case GTIM_CHANNEL_3:
            tmpreg = htim->Instance->CCR3;
            break;
        case GTIM_CHANNEL_4:
            tmpreg = htim->Instance->CCR4;
            break;
        default:
            break;
    }

    return tmpreg;
}

/*******************************************************************************
  * @brief  获取GTIM动作的通道
  * @param  htim    : GTIM句柄指针
  * @retval Active channel
  */
HAL_GTIM_ActiveChannel HAL_GTIM_GetActiveChannel(GTIM_HandleTypeDef *htim)
{
    return htim->Channel;
}


/*******************************************************************************
  * GTIM 基础函数:
  * GTIM_Base_SetConfig
  * GTIM_ETR_SetConfig
  * GTIM_CCxChannelCmd
  * GTIM_CCxNChannelCmd
  */

/*******************************************************************************
  * @brief  GTIM 时基配置
  * @param  TIMx     : GTIM实体指针
  * @param  Structure: GTIM时基配置结构体指针
  * @retval None
  */
void GTIM_Base_SetConfig(GTIM_TypeDef *TIMx, GTIM_Base_InitTypeDef *Structure)
{
    // 设置时钟分频 / 计数方向 / 重载模式
    REGBITS_MODIFY(TIMx->CR1,
                   GTIMx_CR1_DIR_Msk | GTIMx_CR1_CMS_Msk |
                   GTIMx_CR1_CKD_Msk | GTIMx_CR1_ARPE_Msk,
                   (uint32_t)Structure->CounterMode      |
                   (uint32_t)Structure->ClockDivision    |
                   (uint32_t)Structure->AutoReloadPreload);

    // 设置自动重载值
    TIMx->ARR = (uint32_t)Structure->Period;

    // 设置预分频值
    TIMx->PSC = Structure->Prescaler;

    TIMx->EGR = GTIMx_EGR_UG_Msk;
}

/*******************************************************************************
  * @brief  GTIM ETR配置
  * @param  TIMx     : GTIM实体指针
  * @param  TIM_ExtTRGPrescaler: ETR预分频
  *            @arg GTIM_ETRPRESCALER_DIV1: ETRP 不分频.
  *            @arg GTIM_ETRPRESCALER_DIV2: ETRP 2分频
  *            @arg GTIM_ETRPRESCALER_DIV4: ETRP 4分频
  *            @arg GTIM_ETRPRESCALER_DIV8: ETRP 8分频
  * @param  TIM_ExtTRGPolarity: ETR极性
  *            @arg GTIM_ETRPOLARITY_INVERTED   : 正相，ETR的高电平或上升沿有效
  *            @arg GTIM_ETRPOLARITY_NONINVERTED: 反相，ETR的低电平或下降沿有效
  * @param  ExtTRGFilter: ETR滤波值
  *            @arg 0x00 ~ 0x0F
  * @retval None
  */
void GTIM_ETR_SetConfig(GTIM_TypeDef *TIMx, uint32_t TIM_ExtTRGPrescaler,
                        uint32_t TIM_ExtTRGPolarity, uint32_t ExtTRGFilter)
{
    REGBITS_MODIFY(TIMx->SMCR,
                   GTIMx_SMCR_ETF_Msk | GTIMx_SMCR_ETPS_Msk | GTIMx_SMCR_ECE_Msk | GTIMx_SMCR_ETP_Msk,
                   TIM_ExtTRGPrescaler | (TIM_ExtTRGPolarity | (ExtTRGFilter << 8U)));
}

/*******************************************************************************
  * @brief  开启或关闭GTIM捕获比较通道x
  * @param  TIMx   : GTIM实体指针
  * @param  Channel: 需要控制的通道
  *                  @arg GTIM_CHANNEL_1: GTIM 通道1
  *                  @arg GTIM_CHANNEL_2: GTIM 通道2
  *                  @arg GTIM_CHANNEL_3: GTIM 通道3
  *                  @arg GTIM_CHANNEL_4: GTIM 通道4
  *                  @arg GTIM_CHANNEL_ALL:  GTIM 所有通道
  * @param  ChannelState: 通道开启或关闭的状态
  *                  @arg GTIM_CCx_ENABLE : 开启通道
  *                  @arg GTIM_CCx_DISABLE: 关闭通道
  * @retval None
  */
void GTIM_CCxChannelCmd(GTIM_TypeDef *TIMx, uint32_t Channel, uint32_t ChannelState)
{
    if (ChannelState == GTIM_CCx_ENABLE)
    {
        TIMx->CCER |= (Channel);
    }
    else
    {
        TIMx->CCER &= ~(Channel);
    }
}


/*******************************************************************************
  * GTIM 内部静态函数:
  * GTIM_OC1_SetConfig
  * GTIM_OC2_SetConfig
  * GTIM_OC3_SetConfig
  * GTIM_OC4_SetConfig
  * GTIM_SlaveTimer_SetConfig
  * GTIM_TI1_ConfigInputStage
  * GTIM_TI2_ConfigInputStage
  * GTIM_TI1_SetConfig
  * GTIM_TI2_SetConfig
  * GTIM_TI3_SetConfig
  * GTIM_TI4_SetConfig
  * GTIM_ITRx_SetConfig
  */

/*******************************************************************************
  * @brief  GTIM输出比较1配置
  * @param  TIMx     : GTIM实体指针
  * @param  OC_Config: 输出配置结构体指针
  * @retval None
  */
static void GTIM_OC1_SetConfig(GTIM_TypeDef *TIMx, GTIM_OC_InitTypeDef *OC_Config)
{
    // 关闭通道1: 复位CC1E
    REGBITS_CLR(TIMx->CCER, GTIMx_CCER_CC1E_Msk);

    // 配置输出比较模式
    REGBITS_MODIFY(TIMx->CCMR1CMP,
                   GTIM_CCMR1CMP_OC1M | GTIMx_CCMR1CAP_CC1S_Msk,
                   (OC_Config->OCMode << 0U));

    TIMx->CCR1 = OC_Config->Pulse;

    // 配置OC1和OC1N的输出极性
    REGBITS_MODIFY(TIMx->CCER,
                   GTIMx_CCER_CC1P_Msk | GTIMx_CCER_CC1NP_Msk,
                   (OC_Config->OCPolarity << 0U));
}

/*******************************************************************************
  * @brief  GTIM输出比较2配置
  * @param  TIMx     : GTIM实体指针
  * @param  OC_Config: 输出配置结构体指针
  * @retval None
  */
static void GTIM_OC2_SetConfig(GTIM_TypeDef *TIMx, GTIM_OC_InitTypeDef *OC_Config)
{
    // 关闭通道2: 复位CC2E和CC2NE
    REGBITS_CLR(TIMx->CCER, GTIMx_CCER_CC2E_Msk);

    // 配置输出比较模式
    REGBITS_MODIFY(TIMx->CCMR1CMP,
                   GTIM_CCMR1CMP_OC2M | GTIMx_CCMR1CAP_CC2S_Msk,
                   (OC_Config->OCMode << 8U));

    TIMx->CCR2 = OC_Config->Pulse;

    // 配置OC2和OC2N的输出极性
    REGBITS_MODIFY(TIMx->CCER,
                   GTIMx_CCER_CC2P_Msk | GTIMx_CCER_CC2NP_Msk,
                   (OC_Config->OCPolarity << 4U));
}

/*******************************************************************************
  * @brief  GTIM输出比较3配置
  * @param  TIMx     : GTIM实体指针
  * @param  OC_Config: 输出配置结构体指针
  * @retval None
  */
static void GTIM_OC3_SetConfig(GTIM_TypeDef *TIMx, GTIM_OC_InitTypeDef *OC_Config)
{
    // 关闭通道3: 复位CC3E和CC3NE
    REGBITS_CLR(TIMx->CCER, GTIMx_CCER_CC3E_Msk);

    // 配置输出比较模式
    REGBITS_MODIFY(TIMx->CCMR2CMP,
                   GTIM_CCMR2CMP_OC3M | GTIMx_CCMR2CAP_CC3S_Msk,
                   (OC_Config->OCMode << 0U));

    TIMx->CCR3 = OC_Config->Pulse;

    // 配置OC3和OC3N的输出极性
    REGBITS_MODIFY(TIMx->CCER,
                   GTIMx_CCER_CC3P_Msk | GTIMx_CCER_CC3NP_Msk,
                   (OC_Config->OCPolarity << 8U));
}

/*******************************************************************************
  * @brief  GTIM输出比较4配置
  * @param  TIMx     : GTIM实体指针
  * @param  OC_Config: 输出配置结构体指针
  * @retval None
  */
static void GTIM_OC4_SetConfig(GTIM_TypeDef *TIMx, GTIM_OC_InitTypeDef *OC_Config)
{
    // 关闭通道4: 复位CC4E和CC4NE
    REGBITS_CLR(TIMx->CCER, GTIMx_CCER_CC4E_Msk);

    // 配置输出比较模式
    REGBITS_MODIFY(TIMx->CCMR2CMP,
                   GTIM_CCMR2CMP_OC4M | GTIMx_CCMR2CAP_CC4S_Msk,
                   (OC_Config->OCMode << 8U));

    TIMx->CCR4 = OC_Config->Pulse;

    // 配置OC4和OC4N的输出极性
    REGBITS_MODIFY(TIMx->CCER,
                   GTIMx_CCER_CC4P_Msk | GTIMx_CCER_CC4NP_Msk,
                   (OC_Config->OCPolarity << 12U));
}

/*******************************************************************************
  * @brief  GTIM从模式配置
  * @param  TIMx        : GTIM实体指针
  * @param  sSlaveConfig: 从模式配置结构体指针
  * @retval HAL status
  */
static HAL_StatusTypeDef GTIM_SlaveTimer_SetConfig(GTIM_HandleTypeDef *htim,
                                                   GTIM_SlaveConfigTypeDef *sSlaveConfig)
{
    uint32_t tmpccer;

    REGBITS_MODIFY(htim->Instance->SMCR,
                   GTIM_SMCR_TS | GTIM_SMCR_SMS,
                   (uint32_t)sSlaveConfig->InputTrigger | (uint32_t)sSlaveConfig->SlaveMode);

    // 配置触发输入的预分频，滤波和极性
    switch (sSlaveConfig->InputTrigger)
    {
        case GTIM_TS_ETRF:
        {
            GTIM_ETR_SetConfig(htim->Instance,
                               sSlaveConfig->TriggerPrescaler,
                               sSlaveConfig->TriggerPolarity,
                               sSlaveConfig->TriggerFilter);
            break;
        }
        case GTIM_TS_TI1F_ED:
        {
            if ((sSlaveConfig->SlaveMode == GTIM_SLAVEMODE_GATED) ||
                (sSlaveConfig->SlaveMode == GTIM_SLAVEMODE_COMBINED_GATEDRESET))
            {
                return HAL_ERROR;
            }
            // 关闭通道1设置完滤波之后再开启
            tmpccer = htim->Instance->CCER;
            REGBITS_CLR(htim->Instance->CCER, GTIMx_CCER_CC1E_Msk);
            REGBITS_MODIFY(htim->Instance->CCMR1CAP,
                           GTIMx_CCMR1CAP_IC1F_Msk,
                           ((sSlaveConfig->TriggerFilter) << 4U));
            htim->Instance->CCER = tmpccer;
            break;
        }
        case GTIM_TS_TI1FP1:
        {
            // 配置TI1的滤波和极性
            GTIM_TI1_ConfigInputStage(htim->Instance,
                                      sSlaveConfig->TriggerPolarity,
                                      sSlaveConfig->TriggerFilter);
            break;
        }
        case GTIM_TS_TI2FP2:
        {
            // 配置TI2的滤波和极性
            GTIM_TI2_ConfigInputStage(htim->Instance,
                                      sSlaveConfig->TriggerPolarity,
                                      sSlaveConfig->TriggerFilter);
            break;
        }
        case GTIM_TS_ITR0:
        case GTIM_TS_ITR1:
        case GTIM_TS_ITR2:
        case GTIM_TS_ITR3:
        case GTIM_TS_ITR4:
        case GTIM_TS_ITR5:
        case GTIM_TS_ITR6:
        case GTIM_TS_ITR7:
        case GTIM_TS_ITR8:
        case GTIM_TS_ITR11:
        case GTIM_TS_ITR12:
        {
            break;
        }

        default:
            break;
    }
    return HAL_OK;
}

/*******************************************************************************
  * @brief  配置TI1的极性和滤波
  * @param  TIMx          : GTIM实体指针
  * @param  TIM_ICPolarity: 输入极性
  *                         @arg GTIM_ICPOLARITY_RISING
  *                         @arg GTIM_ICPOLARITY_FALLING
  *                         @arg GTIM_ICPOLARITY_BOTHEDGE
  * @param  TIM_ICFilter  : 输入滤波
  *                         @arg 0x00 ~ 0x0F
  * @retval None
  */
static void GTIM_TI1_ConfigInputStage(GTIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter)
{
    uint32_t tmpccer;

    // 关闭通道1: 复位CC1E
    tmpccer = TIMx->CCER;
    REGBITS_CLR(TIMx->CCER, GTIMx_CCER_CC1E_Msk);

    // 设置滤波
    REGBITS_MODIFY(TIMx->CCMR1CAP, GTIMx_CCMR1CAP_IC1F_Msk, (TIM_ICFilter << 4U));

    // 设置极性
    tmpccer &= ~(GTIMx_CCER_CC1P_Msk | GTIMx_CCER_CC1NP_Msk);
    tmpccer |= TIM_ICPolarity;

    // 重新写入CCER寄存器
    TIMx->CCER = tmpccer;
}

/*******************************************************************************
  * @brief  配置TI2的极性和滤波
  * @param  TIMx          : GTIM实体指针
  * @param  TIM_ICPolarity: 输入极性
  *                         @arg GTIM_ICPOLARITY_RISING
  *                         @arg GTIM_ICPOLARITY_FALLING
  *                         @arg GTIM_ICPOLARITY_BOTHEDGE
  * @param  TIM_ICFilter  : 输入滤波
  *                         @arg 0x00 ~ 0x0F
  * @retval None
  */
static void GTIM_TI2_ConfigInputStage(GTIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter)
{
    uint32_t tmpccer;

    // 关闭通道2: 复位CC2E/
    tmpccer = TIMx->CCER;
    REGBITS_CLR(TIMx->CCER, GTIMx_CCER_CC2E_Msk);

    // 设置滤波
    REGBITS_MODIFY(TIMx->CCMR1CAP, GTIMx_CCMR1CAP_IC2F_Msk, (TIM_ICFilter << 12U));

    // 设置极性
    tmpccer &= ~(GTIMx_CCER_CC2P_Msk | GTIMx_CCER_CC2NP_Msk);
    tmpccer |= (TIM_ICPolarity << 4U);

    // 重新写入CCER寄存器
    TIMx->CCER = tmpccer;
}

/*******************************************************************************
  * @brief  配置TI1作为输入
  * @param  TIMx           : GTIM实体指针
  * @param  TIM_ICPolarity : 输入极性
  *                          @arg GTIM_ICPOLARITY_RISING
  *                          @arg GTIM_ICPOLARITY_FALLING
  *                          @arg GTIM_ICPOLARITY_BOTHEDGE
  * @param  TIM_ICSelection: 输入选择
  *                          @arg GTIM_ICSELECTION_DIRECTTI:   IC1映射到TI1上
  *                          @arg GTIM_ICSELECTION_INDIRECTTI: IC1映射到TI2上
  *                          @arg GTIM_ICSELECTION_TRGI:       IC1映射到TRGI上
  * @param  TIM_ICFilter   : 输入滤波
  *                          @arg 0x00 ~ 0x0F
  * @retval None
  * @note   当输入选择为 GTIM_ICSELECTION_INDIRECTTI 时传入的输入极性和输入滤波不起作用，此时
  *         用户需要保证 CCMR1CAP 不受未初始化的滤波器和极性值的影响。
  */
static void GTIM_TI1_SetConfig(GTIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
                               uint32_t TIM_ICFilter)
{
    // 关闭通道1
    REGBITS_CLR(TIMx->CCER, GTIMx_CCER_CC1E_Msk);

    // 设置输入源和输入滤波
    REGBITS_MODIFY(TIMx->CCMR1CAP,
                   GTIMx_CCMR1CAP_CC1S_Msk | GTIMx_CCMR1CAP_IC1F_Msk,
                   TIM_ICSelection | ((TIM_ICFilter << 4U) & GTIMx_CCMR1CAP_IC1F_Msk));

    // 设置输入极性
    REGBITS_MODIFY(TIMx->CCER,
                   GTIMx_CCER_CC1P_Msk | GTIMx_CCER_CC1NP_Msk,
                   TIM_ICPolarity & (GTIMx_CCER_CC1P_Msk | GTIMx_CCER_CC1NP_Msk));
}

/*******************************************************************************
  * @brief  配置TI2作为输入
  * @param  TIMx           : GTIM实体指针
  * @param  TIM_ICPolarity : 输入极性
  *                          @arg GTIM_ICPOLARITY_RISING
  *                          @arg GTIM_ICPOLARITY_FALLING
  *                          @arg GTIM_ICPOLARITY_BOTHEDGE
  * @param  TIM_ICSelection: 输入选择
  *                          @arg GTIM_ICSELECTION_DIRECTTI:   IC2映射到TI2上
  *                          @arg GTIM_ICSELECTION_INDIRECTTI: IC2映射到TI1上
  *                          @arg GTIM_ICSELECTION_TRGI:       IC2映射到TRGI上
  * @param  TIM_ICFilter   : 输入滤波
  *                          @arg 0x00 ~ 0x0F
  * @retval None
  * @note   当输入选择为 GTIM_ICSELECTION_INDIRECTTI 时传入的输入极性和输入滤波不起作用，此时
  *         用户需要保证 CCMR1CAP 不受未初始化的滤波器和极性值的影响。
  */
static void  GTIM_TI2_SetConfig(GTIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
                                uint32_t TIM_ICFilter)
{
    // 关闭通道2
    REGBITS_CLR(TIMx->CCER, GTIMx_CCER_CC2E_Msk);

    // 设置输入源和输入滤波
    REGBITS_MODIFY(TIMx->CCMR1CAP,
                   GTIMx_CCMR1CAP_CC2S_Msk | GTIMx_CCMR1CAP_IC2F_Msk,
                   (TIM_ICSelection << 8U) | ((TIM_ICFilter << 12U) & GTIMx_CCMR1CAP_IC2F_Msk));

    // 设置输入极性
    REGBITS_MODIFY(TIMx->CCER,
                   (GTIMx_CCER_CC2P_Msk | GTIMx_CCER_CC2NP_Msk),
                   (TIM_ICPolarity << 4U) & (GTIMx_CCER_CC2P_Msk | GTIMx_CCER_CC2NP_Msk));
}

/*******************************************************************************
  * @brief  配置TI3作为输入
  * @param  TIMx           : GTIM实体指针
  * @param  TIM_ICPolarity : 输入极性
  *                          @arg GTIM_ICPOLARITY_RISING
  *                          @arg GTIM_ICPOLARITY_FALLING
  *                          @arg GTIM_ICPOLARITY_BOTHEDGE
  * @param  TIM_ICSelection: 输入选择
  *                          @arg GTIM_ICSELECTION_DIRECTTI:   IC3映射到TI3上
  *                          @arg GTIM_ICSELECTION_INDIRECTTI: IC3映射到TI4上
  *                          @arg GTIM_ICSELECTION_TRGI:       IC3映射到TRGI上
  * @param  TIM_ICFilter   : 输入滤波
  *                          @arg 0x00 ~ 0x0F
  * @retval None
  * @note   当输入选择为 GTIM_ICSELECTION_INDIRECTTI 时传入的输入极性和输入滤波不起作用，此时
  *         用户需要保证 CCMR2CAP 不受未初始化的滤波器和极性值的影响。
  */
static void GTIM_TI3_SetConfig(GTIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
                               uint32_t TIM_ICFilter)
{
    // 关闭通道3
    REGBITS_CLR(TIMx->CCER, GTIMx_CCER_CC3E_Msk);

    // 设置输入源和输入滤波
    REGBITS_MODIFY(TIMx->CCMR2CAP,
                   GTIMx_CCMR2CAP_CC3S_Msk | GTIMx_CCMR2CAP_IC3F_Msk,
                   TIM_ICSelection | ((TIM_ICFilter << 4U) & GTIMx_CCMR2CAP_IC3F_Msk));

    // 设置输入极性
    REGBITS_MODIFY(TIMx->CCER,
                   GTIMx_CCER_CC3P_Msk | GTIMx_CCER_CC3NP_Msk,
                   (TIM_ICPolarity << 8U) & (GTIMx_CCER_CC3P_Msk | GTIMx_CCER_CC3NP_Msk));
}

/*******************************************************************************
  * @brief  配置TI4作为输入
  * @param  TIMx           : GTIM实体指针
  * @param  TIM_ICPolarity : 输入极性
  *                          @arg GTIM_ICPOLARITY_RISING
  *                          @arg GTIM_ICPOLARITY_FALLING
  *                          @arg GTIM_ICPOLARITY_BOTHEDGE
  * @param  TIM_ICSelection: 输入选择
  *                          @arg GTIM_ICSELECTION_DIRECTTI:   IC4映射到TI4上
  *                          @arg GTIM_ICSELECTION_INDIRECTTI: IC4映射到TI3上
  *                          @arg GTIM_ICSELECTION_TRGI:       IC4映射到TRGI上
  * @param  TIM_ICFilter   : 输入滤波
  *                          @arg 0x00 ~ 0x0F
  * @retval None
  * @note   当输入选择为 GTIM_ICSELECTION_INDIRECTTI 时传入的输入极性和输入滤波不起作用，此时
  *         用户需要保证 CCMR2CAP 不受未初始化的滤波器和极性值的影响。
  */
static void GTIM_TI4_SetConfig(GTIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
                               uint32_t TIM_ICFilter)
{
    // 关闭通道4
    REGBITS_CLR(TIMx->CCER, GTIMx_CCER_CC4E_Msk);

    // 设置输入源和输入滤波
    REGBITS_MODIFY(TIMx->CCMR2CAP,
                   GTIMx_CCMR2CAP_CC4S_Msk | GTIMx_CCMR2CAP_IC4F_Msk,
                   (TIM_ICSelection << 8U) | ((TIM_ICFilter << 12U) & GTIMx_CCMR2CAP_IC4F_Msk));

    // 设置输入极性
    REGBITS_MODIFY(TIMx->CCER,
                   GTIMx_CCER_CC4P_Msk | GTIMx_CCER_CC4NP_Msk,
                   (TIM_ICPolarity << 12U) & (GTIMx_CCER_CC4P_Msk | GTIMx_CCER_CC4NP_Msk));
}

/*******************************************************************************
  * @brief  配置ITR触发输入源
  * @param  TIMx               : GTIM实体指针
  * @param  InputTriggerSource : 触发输入源
  *                              @arg GTIM_TS_ITR0: 内部触发0，无功能
  *                              @arg GTIM_TS_ITR1: 内部触发1，无功能
  *                              @arg GTIM_TS_ITR2: 内部触发2，GTIM1_TRGO
  *                              @arg GTIM_TS_ITR3: 内部触发3，无功能
  *                              @arg GTIM_TS_TI1F_ED: TI1 边沿监测
  *                              @arg GTIM_TS_TI1FP1: 滤波后的定时器输入1
  *                              @arg GTIM_TS_TI2FP2: 滤波后的定时器输入2
  *                              @arg GTIM_TS_ETRF: 外部触发输入
  *                              @arg GTIM_TS_ITR4: 内部触发4，无功能
  *                              @arg GTIM_TS_ITR5: 内部触发5，无功能
  *                              @arg GTIM_TS_ITR6: 内部触发6，UART1_TXD
  *                              @arg GTIM_TS_ITR7: 内部触发7，UART2_TXD
  *                              @arg GTIM_TS_ITR8: 内部触发8，UART1_TXD
  *                              @arg GTIM_TS_ITR9: 内部触发9，UART2_TXD
  *                              @arg GTIM_TS_ITR10: 内部触发10，BTIM1_TRGO
  *                              @arg GTIM_TS_ITR11: 内部触发11，BTIM1_TRGO
  *                              @arg GTIM_TS_ITR12: 内部触发12，BTIM1_TRGO
  * @retval None
  */
static void GTIM_ITRx_SetConfig(GTIM_TypeDef *TIMx, uint32_t InputTriggerSource)
{
    REGBITS_MODIFY(TIMx->SMCR, GTIM_SMCR_TS | GTIM_SMCR_SMS,
                   (InputTriggerSource | GTIM_SLAVEMODE_EXTERNAL1));
}


/*******************************************************************************
  * GTIM 扩展的控制函数:
  * HAL_GTIM_MasterConfigSynchronization
  * HAL_GTIM_RemapConfig
  * HAL_GTIM_ETRSelection
  * HAL_GTIM_TISelection
  * HAL_GTIM_ConfigSlaveModePreload
  * HAL_GTIM_EnableSlaveModePreload
  * HAL_GTIM_DisableSlaveModePreload
  * HAL_GTIM_ConfigEncoderIndex
  * HAL_GTIM_EnableEncoderIndex
  * HAL_GTIM_DisableEncoderIndex
  * HAL_GTIM_EnableEncoderFirstIndex
  * HAL_GTIM_DisableEncoderFirstIndex
  */

/*******************************************************************************
  * @brief  配置GTIM 工作于主模式
  * @param  htim             : GTIM句柄指针
  * @param  sMasterConfig    : GTIM主模式配置结构体指针，用于设置TRGO和主从模式
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_MasterConfigSynchronization(GTIM_HandleTypeDef *htim,
                                                       GTIM_MasterConfigTypeDef *sMasterConfig)
{
    // 配置TRGO
    REGBITS_MODIFY(htim->Instance->CR2, GTIM_CR2_MMS, sMasterConfig->MasterOutputTrigger);

    // 配置主从模式MSM
    REGBITS_MODIFY(htim->Instance->SMCR, GTIMx_SMCR_MSM_Msk, sMasterConfig->MasterSlaveMode);

    return HAL_OK;
}

/*******************************************************************************
  * @brief  GTIM ETR输入源选择
  * @param  htim         : GTIM句柄指针
  * @param  ETRSelection : 指定的ETR输入源，可选以下参数:
  *                        @arg GTIM_ETRSEL_GPIO     : ETR 管脚 作为ETR信号来源
  *                        @arg GTIM_ETRSEL_VC1_OUT  : VC1_OUT 作为ETR信号来源
  *                        @arg GTIM_ETRSEL_VC2_OUT  : VC2_OUT 作为ETR信号来源
  *                        @arg GTIM_ETRSEL_ADC_AWD  : ADC_AWD 作为ETR信号来源
  *                        @arg GTIM_ETRSEL_HSE_FAULT: HSE_FAULT 作为ETR信号来源
  *                        @arg GTIM_ETRSEL_LVD_OUT  : LVD_OUT 作为ETR信号来源
  *                        @arg GTIM_ETRSEL_UART1_TXD: UART1_TXD 作为ETR信号来源
  *                        @arg GTIM_ETRSEL_UART2_TXD: UART2_TXD 作为ETR信号来源
  *                        @arg GTIM_ETRSEL_LSE_FAULT: LSE_FAULT 作为ETR信号来源
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_ETRSelection(GTIM_HandleTypeDef *htim, uint32_t ETRSelection)
{
    REGBITS_MODIFY(htim->Instance->AF1, GTIMx_AF1_ETRSEL_Msk, ETRSelection);
    return HAL_OK;
}

HAL_StatusTypeDef HAL_GTIM_RemapConfig(GTIM_HandleTypeDef *htim, uint32_t Remap)
{
    return HAL_GTIM_ETRSelection(htim, Remap);
}

/*******************************************************************************
  * @brief  GTIM TI输入源选择
  * @param  htim        : GTIM句柄指针
  * @param  TISelection : 指定的ETR输入源，可选以下参数:
  *                      @ref GTIM_TIxSEL_GPIO      : GPIO       作为CHx输入捕获来源
  *                      @ref GTIM_TIxSEL_VC1_OUT   : VC1_OUT    作为CHx输入捕获来源
  *                      @ref GTIM_TIxSEL_VC2_OUT   : VC2_OUT    作为CHx输入捕获来源
  *                      @ref GTIM_TIxSEL_UART1_RXD : UART1_RXD  作为CHx输入捕获来源
  *                      @ref GTIM_TIxSEL_UART2_RXD : UART2_RXD  作为CHx输入捕获来源
  *                      @ref GTIM_TIxSEL_MCO_OUT   : MCO_OUT    作为CHx输入捕获来源
  *                      @ref GTIM_TIxSEL_HSE_FAULT : HSE_FAULT  作为CHx输入捕获来源
  *                      @ref GTIM_TIxSEL_LSE_FAULT : LSE_FAULT  作为CHx输入捕获来源
  *                      @ref GTIM_TIxSEL_RTC_OUT   : RTC_OUT    作为CHx输入捕获来源
  *                      @ref GTIM_TIxSEL_LSI_OUT   : LSI_OUT    作为CHx输入捕获来源
  *                      @ref GTIM_TIxSEL_BTIM1_TRGO: BTIM1_Trgo 作为CHx输入捕获来源
  *                      @ref GTIM_TIxSEL_BTIM2_TRGO: BTIM2_Trgo 作为CHx输入捕获来源
  *                      @ref GTIM_TIxSEL_BTIM3_TRGO: BTIM3_Trgo 作为CHx输入捕获来源
  *                      @ref GTIM_TIxSEL_ATIM_TRGO : ATIM_Trgo 作为CHx输入捕获来源
  * @param  Channel    : 需要设置TI输入源的通道，可选以下参数:
  *                      @arg GTIM_CHANNEL_1: GTIM 通道1
  *                      @arg GTIM_CHANNEL_2: GTIM 通道2
  *                      @arg GTIM_CHANNEL_3: GTIM 通道3
  *                      @arg GTIM_CHANNEL_4: GTIM 通道4
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_TISelection(GTIM_HandleTypeDef *htim, uint32_t TISelection, uint32_t Channel)
{
    HAL_StatusTypeDef status = HAL_OK;

    switch (Channel)
    {
        case GTIM_CHANNEL_1:
            REGBITS_MODIFY(htim->Instance->TISEL, GTIMx_TISEL_TI1SEL_Msk, (TISelection) << 0);
            break;
        case GTIM_CHANNEL_2:
            REGBITS_MODIFY(htim->Instance->TISEL, GTIMx_TISEL_TI2SEL_Msk, (TISelection) << 8);
            break;
        case GTIM_CHANNEL_3:
            REGBITS_MODIFY(htim->Instance->TISEL, GTIMx_TISEL_TI3SEL_Msk, (TISelection) << 16);
            break;
        case GTIM_CHANNEL_4:
            REGBITS_MODIFY(htim->Instance->TISEL, GTIMx_TISEL_TI4SEL_Msk, (TISelection) << 24);
            break;
        default:
            status = HAL_ERROR;
            break;
    }

    return status;
}

/*******************************************************************************
  * @brief  从模式选择控制位(SMS)的预加载条件配置
  * @param  htim       : GTIM句柄指针
  * @param  Source     : SMS控制位更新影子寄存器条件，可选以下参数:
  *                      @arg GTIM_SMS_PRELOAD_SOURCE_UPDATE: 发生更新事件时更新SMS的影子寄存器
  *                      @arg GTIM_SMS_PRELOAD_SOURCE_INDEX:  发生索引事件时更新SMS的影子寄存器
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_ConfigSlaveModePreload(GTIM_HandleTypeDef *htim, uint32_t Source)
{
    REGBITS_MODIFY(htim->Instance->SMCR, GTIMx_SMCR_SMSPS_Msk, Source);
    return HAL_OK;
}

/*******************************************************************************
  * @brief  使能SMS控制位预装载
  * @param  htim       : GTIM句柄指针
  * @retval HAL status
  * @note   向SMS位写入数据后，满足SMSPS所指定的条件时才更新影子寄存器。
  */
HAL_StatusTypeDef HAL_GTIM_EnableSlaveModePreload(GTIM_HandleTypeDef *htim)
{
    REGBITS_SET(htim->Instance->SMCR, GTIMx_SMCR_SMSPE_Msk);
    return HAL_OK;
}

/*******************************************************************************
  * @brief  禁止SMS控制位预装载
  * @param  htim       : GTIM句柄指针
  * @retval HAL status
  * @note   向SMS位写入数据后，立即更新影子寄存器。
  */
HAL_StatusTypeDef HAL_GTIM_DisableSlaveModePreload(GTIM_HandleTypeDef *htim)
{
    REGBITS_CLR(htim->Instance->SMCR, GTIMx_SMCR_SMSPE_Msk);
    return HAL_OK;
}

/*******************************************************************************
  * @brief  配置编码器索引信号
  * @param  htim               : GTIM句柄指针
  * @param  sEncoderIndexConfig: 编码器索引信号配置结构体指针
  * @retval HAL status
  * @note   编码器模式设置为时钟+方向模式时，计数方向必须设置为 @ref GTIM_ENCODERINDEX_DIRECTION_UP_DOWN
  */
HAL_StatusTypeDef HAL_GTIM_ConfigEncoderIndex(GTIM_HandleTypeDef *htim,
                                              GTIM_EncoderIndexConfigTypeDef *sEncoderIndexConfig)
{
    // 配置ETR用作索引输入的外部触发
    GTIM_ETR_SetConfig(htim->Instance,
                       sEncoderIndexConfig->Prescaler,
                       sEncoderIndexConfig->Polarity,
                       sEncoderIndexConfig->Filter);

    // 配置编码索引信号
    REGBITS_MODIFY(htim->Instance->ECR,
                   GTIMx_ECR_IDIR_Msk | GTIMx_ECR_FIDX_Msk | GTIMx_ECR_IPOS_Msk,
                   (uint32_t)sEncoderIndexConfig->Direction |
                   (uint32_t)sEncoderIndexConfig->Position  |
                   ((sEncoderIndexConfig->FirstIndexEnable == ENABLE) ? GTIMx_ECR_FIDX_Msk : 0U) |
                   GTIMx_ECR_IE_Msk);

    return HAL_OK;
}

/*******************************************************************************
  * @brief  使能编码索引信号重置计数器
  * @param  htim       : GTIM句柄指针
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_EnableEncoderIndex(GTIM_HandleTypeDef *htim)
{
    REGBITS_SET(htim->Instance->ECR, GTIMx_ECR_IE_Msk);
    return HAL_OK;
}

/*******************************************************************************
  * @brief  禁止编码索引信号重置计数器
  * @param  htim       : GTIM句柄指针
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_DisableEncoderIndex(GTIM_HandleTypeDef *htim)
{
    REGBITS_CLR(htim->Instance->ECR, GTIMx_ECR_IE_Msk);
    return HAL_OK;
}

/*******************************************************************************
  * @brief  使能编码器首个索引信号
  * @param  htim       : GTIM句柄指针
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_EnableEncoderFirstIndex(GTIM_HandleTypeDef *htim)
{
    REGBITS_SET(htim->Instance->ECR, GTIMx_ECR_FIDX_Msk);
    return HAL_OK;
}

/*******************************************************************************
  * @brief  禁止编码器首个索引信号
  * @param  htim       : GTIM句柄指针
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_GTIM_DisableEncoderFirstIndex(GTIM_HandleTypeDef *htim)
{
    REGBITS_CLR(htim->Instance->ECR, GTIMx_ECR_FIDX_Msk);
    return HAL_OK;
}


/*******************************************************************************
  * @brief  GTIM中断服务程序
  * @param  htim       : GTIM句柄指针
  * @retval HAL status
  */
void HAL_GTIM_IRQHandler(GTIM_HandleTypeDef *htim)
{
    if (HAL_GTIM_GET_FLAG(htim, GTIM_IT_FLAG_CC1) != RESET)           // 捕获比较1事件
    {
        if (HAL_GTIM_GET_IT_SOURCE(htim, GTIM_IT_SOURCE_CC1) != RESET)
        {
            HAL_GTIM_CLEAR_IT(htim, GTIM_IT_SOURCE_CC1);
            htim->Channel = HAL_GTIM_ACTIVE_CHANNEL_1;
            // 输入捕获事件
            if ((htim->Instance->CCMR1CAP & GTIMx_CCMR1CAP_CC1S_Msk) != 0x00U)
            {
                HAL_GTIM_IC_CaptureCallback(htim);
            }
            // 输出比较事件
            else
            {
                HAL_GTIM_OC_DelayElapsedCallback(htim);
                HAL_GTIM_PWM_PulseFinishedCallback(htim);
            }
            htim->Channel = HAL_GTIM_ACTIVE_CHANNEL_CLEARED;
        }
    }
    if (HAL_GTIM_GET_FLAG(htim, GTIM_IT_FLAG_CC2) != RESET)           // 捕获比较2事件
    {
        if (HAL_GTIM_GET_IT_SOURCE(htim, GTIM_IT_SOURCE_CC2) != RESET)
        {
            HAL_GTIM_CLEAR_IT(htim, GTIM_IT_SOURCE_CC2);
            htim->Channel = HAL_GTIM_ACTIVE_CHANNEL_2;
            // 输入捕获事件
            if ((htim->Instance->CCMR1CAP & GTIMx_CCMR1CAP_CC2S_Msk) != 0x00U)
            {
                HAL_GTIM_IC_CaptureCallback(htim);
            }
            // 输出比较事件
            else
            {
                HAL_GTIM_OC_DelayElapsedCallback(htim);
                HAL_GTIM_PWM_PulseFinishedCallback(htim);
            }
            htim->Channel = HAL_GTIM_ACTIVE_CHANNEL_CLEARED;
        }
    }
    if (HAL_GTIM_GET_FLAG(htim, GTIM_IT_FLAG_CC3) != RESET)           // 捕获比较3事件
    {
        if (HAL_GTIM_GET_IT_SOURCE(htim, GTIM_IT_SOURCE_CC3) != RESET)
        {
            HAL_GTIM_CLEAR_IT(htim, GTIM_IT_SOURCE_CC3);
            htim->Channel = HAL_GTIM_ACTIVE_CHANNEL_3;
            // 输入捕获事件
            if ((htim->Instance->CCMR2CAP & GTIMx_CCMR2CAP_CC3S_Msk) != 0x00U)
            {
                HAL_GTIM_IC_CaptureCallback(htim);
            }
            // 输出比较事件
            else
            {
                HAL_GTIM_OC_DelayElapsedCallback(htim);
                HAL_GTIM_PWM_PulseFinishedCallback(htim);
            }
            htim->Channel = HAL_GTIM_ACTIVE_CHANNEL_CLEARED;
        }
    }
    if (HAL_GTIM_GET_FLAG(htim, GTIM_IT_FLAG_CC4) != RESET)           // 捕获比较4事件
    {
        if (HAL_GTIM_GET_IT_SOURCE(htim, GTIM_IT_SOURCE_CC4) != RESET)
        {
            HAL_GTIM_CLEAR_IT(htim, GTIM_IT_SOURCE_CC4);
            htim->Channel = HAL_GTIM_ACTIVE_CHANNEL_4;
            // 输入捕获事件
            if ((htim->Instance->CCMR2CAP & GTIMx_CCMR2CAP_CC4S_Msk) != 0x00U)
            {
                HAL_GTIM_IC_CaptureCallback(htim);
            }
            // 输出比较事件
            else
            {
                HAL_GTIM_OC_DelayElapsedCallback(htim);
                HAL_GTIM_PWM_PulseFinishedCallback(htim);
            }
            htim->Channel = HAL_GTIM_ACTIVE_CHANNEL_CLEARED;
        }
    }
    if (HAL_GTIM_GET_FLAG(htim, GTIM_IT_FLAG_UPDATE) != RESET)        // 更新事件
    {
        if (HAL_GTIM_GET_IT_SOURCE(htim, GTIM_IT_SOURCE_UPDATE) != RESET)
        {
            HAL_GTIM_CLEAR_IT(htim, GTIM_IT_SOURCE_UPDATE);
            HAL_GTIM_PeriodElapsedCallback(htim);
        }
    }
    if (HAL_GTIM_GET_FLAG(htim, GTIM_IT_FLAG_TRIGGER) != RESET)       // 触发检测事件
    {
        if (HAL_GTIM_GET_IT_SOURCE(htim, GTIM_IT_SOURCE_TRIGGER) != RESET)
        {
            HAL_GTIM_CLEAR_IT(htim, GTIM_IT_SOURCE_TRIGGER);
            HAL_GTIM_TriggerCallback(htim);
        }
    }
    if (HAL_GTIM_GET_FLAG(htim, GTIM_IT_FLAG_IDX) != RESET)           // 编码计数索引事件
    {
        if (HAL_GTIM_GET_IT_SOURCE(htim, GTIM_IT_SOURCE_IDX) != RESET)
        {
            HAL_GTIM_CLEAR_IT(htim, GTIM_IT_FLAG_IDX);
            HAL_GTIM_EncoderIndexCallback(htim);
        }
    }
    if (HAL_GTIM_GET_FLAG(htim, GTIM_IT_FLAG_DIR) != RESET)           // 编码计数方向改变事件
    {
        if (HAL_GTIM_GET_IT_SOURCE(htim, GTIM_IT_SOURCE_DIR) != RESET)
        {
            HAL_GTIM_CLEAR_IT(htim, GTIM_IT_FLAG_DIR);
            HAL_GTIM_DirectionChangeCallback(htim);
        }
    }
    if (HAL_GTIM_GET_FLAG(htim, GTIM_IT_FLAG_IERR) != RESET)          // 编码计数索引错误事件
    {
        if (HAL_GTIM_GET_IT_SOURCE(htim, GTIM_IT_SOURCE_IERR) != RESET)
        {
            HAL_GTIM_CLEAR_IT(htim, GTIM_IT_FLAG_IERR);
            HAL_GTIM_IndexErrorCallback(htim);
        }
    }
    if (HAL_GTIM_GET_FLAG(htim, GTIM_IT_FLAG_TERR) != RESET)          // 正交编码转换错误事件
    {
        if (HAL_GTIM_GET_IT_SOURCE(htim, GTIM_IT_SOURCE_TERR) != RESET)
        {
            HAL_GTIM_CLEAR_IT(htim, GTIM_IT_FLAG_TERR);
            HAL_GTIM_TransitionErrorCallback(htim);
        }
    }
}


/*******************************************************************************
  * GTIM 中断服务程序回调函数:
  * HAL_GTIM_PeriodElapsedCallback
  * HAL_GTIM_OC_DelayElapsedCallback
  * HAL_GTIM_IC_CaptureCallback
  * HAL_GTIM_PWM_PulseFinishedCallback
  * HAL_GTIM_TriggerCallback
  * HAL_GTIM_ErrorCallback
  */

/*******************************************************************************
  * @brief  周期完成中断回调函数
  * @param  htim: GTIM 句柄指针
  * @retval None
  * @note   当需要回调时，可以在用户文件中重写本函数，而不应该在此处修改本函数。
  */
__weak void HAL_GTIM_PeriodElapsedCallback(GTIM_HandleTypeDef *htim)
{
    UNUSED(htim);                                                     // 处理未使用的参数防止编译器警告
}

/*******************************************************************************
  * @brief  输出比较中断回调函数
  * @param  htim: GTIM 句柄指针
  * @retval None
  * @note   当需要回调时，可以在用户文件中重写本函数，而不应该在此处修改本函数。
  */
__weak void HAL_GTIM_OC_DelayElapsedCallback(GTIM_HandleTypeDef *htim)
{
    UNUSED(htim);                                                     // 处理未使用的参数防止编译器警告
}

/*******************************************************************************
  * @brief  输入捕获中断回调函数
  * @param  htim: GTIM 句柄指针
  * @retval None
  * @note   当需要回调时，可以在用户文件中重写本函数，而不应该在此处修改本函数。
  */
__weak void HAL_GTIM_IC_CaptureCallback(GTIM_HandleTypeDef *htim)
{
    UNUSED(htim);                                                     // 处理未使用的参数防止编译器警告
}

/*******************************************************************************
  * @brief  PWM脉冲完成中断回调函数
  * @param  htim: GTIM 句柄指针
  * @retval None
  * @note   当需要回调时，可以在用户文件中重写本函数，而不应该在此处修改本函数。
  */
__weak void HAL_GTIM_PWM_PulseFinishedCallback(GTIM_HandleTypeDef *htim)
{
    UNUSED(htim);                                                     // 处理未使用的参数防止编译器警告
}

/*******************************************************************************
  * @brief  触发检测完成中断回调函数
  * @param  htim: GTIM 句柄指针
  * @retval None
  * @note   当需要回调时，可以在用户文件中重写本函数，而不应该在此处修改本函数。
  */
__weak void HAL_GTIM_TriggerCallback(GTIM_HandleTypeDef *htim)
{
    UNUSED(htim);                                                     // 处理未使用的参数防止编译器警告
}

/*******************************************************************************
  * @brief  GTIM出错中断回调函数
  * @param  htim: GTIM 句柄指针
  * @retval None
  * @note   当需要回调时，可以在用户文件中重写本函数，而不应该在此处修改本函数。
  */
__weak void HAL_GTIM_ErrorCallback(GTIM_HandleTypeDef *htim)
{
    UNUSED(htim);                                                     // 处理未使用的参数防止编译器警告
}


/*******************************************************************************
  * GTIM 中断服务程序回调函数(扩展):
  * HAL_GTIM_EncoderIndexCallback
  * HAL_GTIM_DirectionChangeCallback
  * HAL_GTIM_IndexErrorCallback
  * HAL_GTIM_TransitionErrorCallback
  */

/*******************************************************************************
  * @brief  编码计数索引事件中断回调函数
  * @param  htim: GTIM 句柄指针
  * @retval None
  * @note   当需要回调时，可以在用户文件中重写本函数，而不应该在此处修改本函数。
  */
__weak void HAL_GTIM_EncoderIndexCallback(GTIM_HandleTypeDef *htim)
{
    UNUSED(htim);                                                     // 处理未使用的参数防止编译器警告
}

/*******************************************************************************
  * @brief  编码计数方向改变事件中断回调函数
  * @param  htim: GTIM 句柄指针
  * @retval None
  * @note   当需要回调时，可以在用户文件中重写本函数，而不应该在此处修改本函数。
  */
__weak void HAL_GTIM_DirectionChangeCallback(GTIM_HandleTypeDef *htim)
{
    UNUSED(htim);                                                     // 处理未使用的参数防止编译器警告
}

/*******************************************************************************
  * @brief  编码计数索引错误事件中断回调函数
  * @param  htim: GTIM 句柄指针
  * @retval None
  * @note   当需要回调时，可以在用户文件中重写本函数，而不应该在此处修改本函数。
  */
__weak void HAL_GTIM_IndexErrorCallback(GTIM_HandleTypeDef *htim)
{
    UNUSED(htim);                                                     // 处理未使用的参数防止编译器警告
}

/*******************************************************************************
  * @brief  正交编码转换错误事件中断回调函数
  * @param  htim: GTIM 句柄指针
  * @retval None
  * @note   当需要回调时，可以在用户文件中重写本函数，而不应该在此处修改本函数。
  */
__weak void HAL_GTIM_TransitionErrorCallback(GTIM_HandleTypeDef *htim)
{
    UNUSED(htim);                                                     // 处理未使用的参数防止编译器警告
}


/************************ (C) COPYRIGHT SIYIMicro *****END OF FILE*************/
